Skip to content

add flag to exclude a user from aggregates and scoring#4760

Open
lsabor wants to merge 2 commits into
mainfrom
feat/aggregation-blacklist
Open

add flag to exclude a user from aggregates and scoring#4760
lsabor wants to merge 2 commits into
mainfrom
feat/aggregation-blacklist

Conversation

@lsabor
Copy link
Copy Markdown
Contributor

@lsabor lsabor commented May 21, 2026

Summary by CodeRabbit

  • New Features

    • Add per-user "exclude from aggregations" flag to control inclusion in aggregations and peer scoring.
    • Admin UI shows and lets admins filter users by this exclusion status.
  • Bug Fixes

    • Aggregation and scoring routines now consistently respect user exclusion settings across forecasts and history.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72132c1c-3423-44c5-adf9-ebbede6f3b97

📥 Commits

Reviewing files that changed from the base of the PR and between 4823924 and 79eb559.

📒 Files selected for processing (2)
  • users/admin.py
  • users/models.py
✅ Files skipped from review due to trivial changes (1)
  • users/admin.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • users/models.py

📝 Walkthrough

Walkthrough

Adds an indexed exclude_from_aggregations boolean to User, surfaces it in the admin, provides ForecastQuerySet.exclude_blacklisted_users(), and applies that filter in scoring and aggregation code paths to omit flagged users from aggregations.

Changes

User Exclusion from Aggregations

Layer / File(s) Summary
User model field and migration
users/models.py, users/migrations/0021_user_exclude_from_aggregations.py
User model adds indexed exclude_from_aggregations BooleanField with default=False; migration creates the field with DB index and help text.
Admin interface for exclusion field
users/admin.py
UserAdmin.list_display and UserAdmin.list_filter are extended to include exclude_from_aggregations.
QuerySet helper for filtering blacklisted users
questions/models.py
ForecastQuerySet adds exclude_blacklisted_users() which filters forecasts by their author's exclude_from_aggregations flag.
Integration into scoring and aggregation paths
scoring/score_math.py, utils/the_math/aggregations.py
evaluate_question, get_aggregations_at_time, and get_aggregation_history apply exclude_blacklisted_users() to relevant Forecast querysets in their default or filtered branches.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A little flag to keep the sums true,
A hop, a sniff, the bad views unview,
Admin can watch, queries now skip,
Aggregates clean on every script—
Rabbits cheer for tidy review! 🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly summarizes the main change: adding a flag to exclude users from aggregates and scoring, which is reflected across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/aggregation-blacklist

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lsabor lsabor force-pushed the feat/aggregation-blacklist branch from ab153a7 to 4823924 Compare May 21, 2026 21:28
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scoring/score_math.py (1)

361-369: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Blacklisted users are still eligible for peer score rows.

Line 361 keeps user_forecasts unfiltered, and Lines 496-513 still emit per-user scores from that full set. Also, Line 368 only filters base_forecasts when only_include_user_ids is not set. This allows excluded users to still be peer-scored.

Proposed fix
-    user_forecasts = question.user_forecasts.all()
+    user_forecasts = question.user_forecasts.all().exclude_blacklisted_users()
     if only_include_user_ids:
         user_forecasts = user_forecasts.filter(author__id__in=only_include_user_ids)
     base_forecasts = user_forecasts
     if not only_include_user_ids:
         # only include forecasts by non-primary bots if user ids explicitly specified
         base_forecasts = base_forecasts.exclude_non_primary_bots()
-        base_forecasts = base_forecasts.exclude_blacklisted_users()
         if not question.include_bots_in_aggregates:
             base_forecasts = base_forecasts.exclude(author__is_bot=True)

Also applies to: 496-513

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scoring/score_math.py` around lines 361 - 369, The peer-scoring loop is still
using the unfiltered user_forecasts so blacklisted or excluded users can
generate per-user rows; ensure the set used to emit per-user peer scores is
filtered the same way as aggregates by using base_forecasts (or applying
exclude_blacklisted_users()/exclude_non_primary_bots() to user_forecasts) before
the per-user scoring section (the code around user_forecasts, base_forecasts,
exclude_non_primary_bots, exclude_blacklisted_users, include_bots_in_aggregates
and the per-user score emission in the block around lines 496-513). Update the
logic so that when only_include_user_ids is set we still remove
blacklisted/non-primary-bot users from the dataset used to produce peer score
rows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scoring/utils.py`:
- Around line 469-471: The QuerySet assigned to candidates currently selects the
exclude_from_aggregations field but never uses it, so users flagged for
exclusion remain rank-eligible; update the retrieval or post-filtering logic to
enforce exclusion (e.g., add exclude_from_aggregations=False to the
User.objects.filter call or immediately .exclude(exclude_from_aggregations=True)
on the candidates QuerySet) and apply the same change where similar
candidate/user QuerySets are built in the 473-499 region so excluded users are
removed before any ranking or aggregation logic runs.

In `@utils/the_math/aggregations.py`:
- Around line 748-755: The current logic in aggregations.py lets
only_include_user_ids bypass blacklist/bot exclusion: when only_include_user_ids
is provided the code uses forecasts.filter(author_id__in=only_include_user_ids)
but does not call forecasts.exclude_non_primary_bots() or
forecasts.exclude_blacklisted_users(); update the aggregation builders so that
after filtering by only_include_user_ids you also apply
exclude_non_primary_bots() and exclude_blacklisted_users() (or filter out
blacklisted/bot IDs from the provided list) to ensure blacklisted users and
primary bots are always excluded; make the same change in the other occurrence
around the 1002-1009 block.

---

Outside diff comments:
In `@scoring/score_math.py`:
- Around line 361-369: The peer-scoring loop is still using the unfiltered
user_forecasts so blacklisted or excluded users can generate per-user rows;
ensure the set used to emit per-user peer scores is filtered the same way as
aggregates by using base_forecasts (or applying
exclude_blacklisted_users()/exclude_non_primary_bots() to user_forecasts) before
the per-user scoring section (the code around user_forecasts, base_forecasts,
exclude_non_primary_bots, exclude_blacklisted_users, include_bots_in_aggregates
and the per-user score emission in the block around lines 496-513). Update the
logic so that when only_include_user_ids is set we still remove
blacklisted/non-primary-bot users from the dataset used to produce peer score
rows.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 192190df-8943-414a-8b79-6a153b8810c0

📥 Commits

Reviewing files that changed from the base of the PR and between 5b66f09 and ab153a7.

📒 Files selected for processing (7)
  • questions/models.py
  • scoring/score_math.py
  • scoring/utils.py
  • users/admin.py
  • users/migrations/0021_user_exclude_from_aggregations.py
  • users/models.py
  • utils/the_math/aggregations.py

Comment thread scoring/utils.py Outdated
Comment thread utils/the_math/aggregations.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scoring/score_math.py`:
- Around line 365-369: The blacklist exclusion is currently only applied when
not only_include_user_ids, allowing explicit IDs to bypass
exclude_from_aggregations; always apply base_forecasts =
base_forecasts.exclude_blacklisted_users() regardless of the
only_include_user_ids flag. Modify the logic around only_include_user_ids so
that exclude_blacklisted_users() is invoked unconditionally (either move the
call out of the branch or call it in both branches) while keeping
exclude_non_primary_bots() and the question.include_bots_in_aggregates check
behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b34ccdc0-34a6-47c6-abbc-ba5697e09a7c

📥 Commits

Reviewing files that changed from the base of the PR and between ab153a7 and 4823924.

📒 Files selected for processing (6)
  • questions/models.py
  • scoring/score_math.py
  • users/admin.py
  • users/migrations/0021_user_exclude_from_aggregations.py
  • users/models.py
  • utils/the_math/aggregations.py

Comment thread scoring/score_math.py
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Preview Environment

Your preview environment is ready!

Resource Details
🌐 Preview URL https://metaculus-pr-4760-feat-aggregation-blacklist-preview.mtcl.cc
📦 Docker Image ghcr.io/metaculus/metaculus:feat-aggregation-blacklist-4823924
🗄️ PostgreSQL NeonDB branch preview/pr-4760-feat-aggregation-blacklist
Redis Fly Redis mtc-redis-pr-4760-feat-aggregation-blacklist

Details

  • Commit: 8ca8466030685682e72825c8bbd84f8b37e35193
  • Branch: feat/aggregation-blacklist
  • Fly App: metaculus-pr-4760-feat-aggregation-blacklist

ℹ️ Preview Environment Info

Isolation:

  • PostgreSQL and Redis are fully isolated from production
  • Each PR gets its own database branch and Redis instance
  • Changes pushed to this PR will trigger a new deployment

Limitations:

  • Background workers and cron jobs are not deployed in preview environments
  • If you need to test background jobs, use Heroku staging environments

Cleanup:

  • This preview will be automatically destroyed when the PR is closed

@lsabor lsabor requested review from SylvainChevalier and hlbmtc and removed request for hlbmtc May 21, 2026 22:14
@SylvainChevalier
Copy link
Copy Markdown
Contributor

lgtm.

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.

3 participants