Skip to content

Fail closed when gizmoduck user-label lookup is Err or missing - #31

Closed
Pitchfork-and-Torch wants to merge 19 commits into
mainfrom
cursor/gizmoduck-spam-user-label-fail-closed-b00e
Closed

Pitchfork-and-Torch wants to merge 19 commits into
mainfrom
cursor/gizmoduck-spam-user-label-fail-closed-b00e

Conversation

@Pitchfork-and-Torch

Copy link
Copy Markdown
Owner

Bug

GizmoduckAuthorHydrator keeps Failed and omitted gizmoduck reads as Hydrated::Failed. CandidateFeatures::assemble then calls get_or_default, which turns that into empty AuthorFeatures / empty UserLabelSet.

SpamHighRecallUserLabelRule (and sibling OON user-label drops) only check type presence. An empty set is Allow. A store error therefore lets a SpamHighRecall or LowQuality author keep ranking.

Ok(None) / NotFound is a confirmed unlabeled author. That path is unchanged.

This is not xai-org#103 (allowlist store). This is not xai-org#125 (home-mixer origin-author NSFW/size). This is not xai-org#139 (tweet RTF / Manhattan safety-label hydrator). This is the VF gizmoduck consumer of user labels.

Five-line proof

  • Entry: GizmoduckAuthorHydrator / author_lookup_failed (get_or_default used to collapse Err/missing into empty labels)
  • Sink: FilterTweets omit-from-hydrate -> Verdict::unresolved_author Drop
  • Break: gizmoduck Err and omitted id both became unlabeled, so SpamHighRecallUserLabelRule never fired
  • Viewer effect: a SpamHighRecall / LowQuality author whose gizmoduck read missed still ranked
  • Twin: Fail closed when VF safety-label lookup is Err or missing xai-org/x-algorithm#139 fail-closes tweet RTF labels; GetSafetyLabels already tracks failed_ids. This is gizmoduck user labels.

Change

Track Failed / missing gizmoduck author reads. Do not assemble them as default empty labels. retain_candidates_with_usable_author_features omits those ids before assemble. Confirmed NotFound stays unlabeled and serves.

Tests

  • Lookup Err and omitted id are failed (not assembled as empty labels)
  • Confirmed NotFound is not a failure
  • Found SpamHighRecall / LowQuality labels stay usable
  • Retain drops only failed ids
  • Successful labeled / unlabeled reads unchanged

Standalone decision-table harness (same match arms): 11 assertions passed.

cargo test cannot run. Public dump has no VF crate manifest.

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
GizmoduckAuthorHydrator kept Failed/omitted reads in the batch, then
assemble used get_or_default so SpamHighRecall and LowQuality looked
absent. Omit those ids before assemble. Confirmed NotFound stays unlabeled.

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