Upload folder using huggingface_hub
Browse files- DESIGN.md +64 -29
- README.md +181 -222
- artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json +0 -0
- artifacts/baselines/canonical_qwen2.5_72b_hf_seed7_manifest_2026-04-03.2.json +0 -0
- inference.py +9 -1
- server/data/scenarios_easy.json +182 -187
- server/data/scenarios_hard.json +84 -63
- server/data/scenarios_medium.json +117 -108
DESIGN.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
| 1 |
# SafeSpace Design Document
|
| 2 |
|
| 3 |
-
This document explains the design decisions behind SafeSpace, a content moderation RL environment. It serves as both an internal reference and a public explanation of the benchmark
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
---
|
| 6 |
|
|
@@ -100,11 +112,10 @@ We model three concrete moderation workflows rather than three abstract buckets:
|
|
| 100 |
|
| 101 |
We separate the environment into two evaluation layers:
|
| 102 |
|
| 103 |
-
- **Canonical benchmark:** 60
|
| 104 |
-
- **Full corpus:** 367 total scenarios used for broader regression testing and stress coverage
|
| 105 |
|
| 106 |
The canonical benchmark is the headline score we report in the README and baseline script. The full corpus still matters, but we do not treat metadata-only procedural variants as benchmark depth.
|
| 107 |
-
Manifest version `2026-04-03.2` also rebalances the hard split away from a remove-heavy concentration by adding one escalation case, one approve satire case, and one warn coded-hate case from the existing corpus.
|
| 108 |
|
| 109 |
### Decision Distribution (Hard Tier)
|
| 110 |
|
|
@@ -144,7 +155,7 @@ This is low enough to discourage always-escalate strategies while still rewardin
|
|
| 144 |
|
| 145 |
### Repeat Offender Scenarios
|
| 146 |
|
| 147 |
-
|
| 148 |
|
| 149 |
### Calibration Mechanics
|
| 150 |
|
|
@@ -236,30 +247,7 @@ We evaluate agents on:
|
|
| 236 |
|
| 237 |
### Reference Runs
|
| 238 |
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
`artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json`
|
| 242 |
-
|
| 243 |
-
This run uses `gpt-5.4` through an OpenAI-compatible Azure AI Foundry endpoint with `OPENAI_SEED=7` on manifest version `2026-04-03.2`.
|
| 244 |
-
|
| 245 |
-
| Tier | Avg Task Grade | Avg Reward | Avg Raw Reward |
|
| 246 |
-
|------|----------------|------------|----------------|
|
| 247 |
-
| Easy | 0.8244 | 0.7760 | 0.7200 |
|
| 248 |
-
| Medium | 0.4934 | 0.4914 | 0.3643 |
|
| 249 |
-
| Hard | 0.4213 | 0.4695 | 0.3369 |
|
| 250 |
-
|
| 251 |
-
Secondary open-weight comparison artifact:
|
| 252 |
-
|
| 253 |
-
`artifacts/baselines/canonical_qwen2.5_72b_hf_seed7_manifest_2026-04-03.2.json`
|
| 254 |
-
|
| 255 |
-
This comparison run uses `Qwen/Qwen2.5-72B-Instruct` via the Hugging Face Router with `OPENAI_SEED=7`.
|
| 256 |
-
|
| 257 |
-
| Model | Avg Task Grade | Avg Reward | Avg Raw Reward |
|
| 258 |
-
|-------|----------------|------------|----------------|
|
| 259 |
-
| `gpt-5.4` | 0.5797 | 0.5790 | 0.4737 |
|
| 260 |
-
| `Qwen/Qwen2.5-72B-Instruct` | 0.4775 | 0.5098 | 0.3873 |
|
| 261 |
-
|
| 262 |
-
These numbers are reference points, not normative targets. The benchmark remains intentionally challenging on context-dependent and hard policy-review cases, and score movement should be interpreted relative to the same manifest and inference setup.
|
| 263 |
|
| 264 |
---
|
| 265 |
|
|
@@ -296,3 +284,50 @@ SafeSpace is designed around these principles:
|
|
| 296 |
5. **Principled defaults**: Episode budget, trajectory caps, score ranges all have explicit rationale
|
| 297 |
|
| 298 |
The goal is an environment that teaches real moderation skills, not pattern matching or hedging strategies.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# SafeSpace Design Document
|
| 2 |
|
| 3 |
+
This document explains the design decisions behind SafeSpace, a content moderation RL environment. It serves as both an internal reference and a public explanation of the benchmark's design choices.
|
| 4 |
+
|
| 5 |
+
For setup instructions, action and observation spaces, and usage examples, see `README.md`. This document is focused on benchmark rationale: why the environment is structured this way, how reward and grading were chosen, and what design tradeoffs shape the evaluation.
|
| 6 |
+
|
| 7 |
+
## Executive Summary
|
| 8 |
+
|
| 9 |
+
SafeSpace is built around five core design choices:
|
| 10 |
+
|
| 11 |
+
1. **Moderation is treated as a sequential decision problem, not a one-shot classifier.** Agents must decide when context is necessary and when acting immediately is better.
|
| 12 |
+
2. **Reward and evaluation are aligned.** Training reward and benchmark grading preserve the same ordering of outcomes so agents are not incentivized to exploit mismatched objectives.
|
| 13 |
+
3. **The benchmark is designed to resist easy gaming.** Adjacent decisions receive limited credit, calibration matters, and scenario distributions are balanced enough to discourage trivial hedging strategies.
|
| 14 |
+
4. **Deterministic grading is a feature, not a limitation.** SafeSpace avoids LLM judges in order to maximize reproducibility, auditability, and low-cost evaluation.
|
| 15 |
+
5. **The environment emphasizes realistic moderation ambiguity within a constrained scope.** Context dependence, policy exceptions, repeat-offender logic, and escalation are in scope; multimodal reasoning and multi-agent workflows are intentionally out of scope for now.
|
| 16 |
|
| 17 |
---
|
| 18 |
|
|
|
|
| 112 |
|
| 113 |
We separate the environment into two evaluation layers:
|
| 114 |
|
| 115 |
+
- **Canonical benchmark:** 60 authored submission scenarios, 20 per task, defined in `server/data/benchmark_manifest.json`
|
| 116 |
+
- **Full corpus:** 367 total scenarios used for broader regression testing and stress coverage, including non-canonical procedural variants
|
| 117 |
|
| 118 |
The canonical benchmark is the headline score we report in the README and baseline script. The full corpus still matters, but we do not treat metadata-only procedural variants as benchmark depth.
|
|
|
|
| 119 |
|
| 120 |
### Decision Distribution (Hard Tier)
|
| 121 |
|
|
|
|
| 155 |
|
| 156 |
### Repeat Offender Scenarios
|
| 157 |
|
| 158 |
+
A substantial subset of hard scenarios feature borderline content where repeat-offender history pushes the correct outcome toward `remove`. This tests whether agents can integrate author history with surface content analysis, not just pattern-match on text.
|
| 159 |
|
| 160 |
### Calibration Mechanics
|
| 161 |
|
|
|
|
| 247 |
|
| 248 |
### Reference Runs
|
| 249 |
|
| 250 |
+
Reference runs are useful calibration points, but they are not the benchmark's core design rationale. Exact baseline numbers are best interpreted relative to a specific manifest version, model endpoint, and inference configuration, so the current benchmark snapshot is included in the appendix below rather than treated as a permanent part of the design argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
|
| 252 |
---
|
| 253 |
|
|
|
|
| 284 |
5. **Principled defaults**: Episode budget, trajectory caps, score ranges all have explicit rationale
|
| 285 |
|
| 286 |
The goal is an environment that teaches real moderation skills, not pattern matching or hedging strategies.
|
| 287 |
+
|
| 288 |
+
---
|
| 289 |
+
|
| 290 |
+
## Appendix: Current Benchmark Snapshot
|
| 291 |
+
|
| 292 |
+
This appendix captures the current shipped benchmark snapshot. It is intentionally separated from the main design rationale because these details may change over time as the corpus, manifest, or reference runs evolve.
|
| 293 |
+
|
| 294 |
+
### Current Manifest Snapshot
|
| 295 |
+
|
| 296 |
+
- Canonical benchmark: 60 authored submission scenarios, 20 per task
|
| 297 |
+
- Full corpus: 367 total scenarios, including broader regression/stress coverage outside the canonical benchmark
|
| 298 |
+
- Current manifest version: `2026-04-03.2`
|
| 299 |
+
|
| 300 |
+
This manifest rebalances the hard split away from an overly remove-heavy concentration while preserving the same task framing and grading philosophy described above.
|
| 301 |
+
|
| 302 |
+
### Current Reference Runs
|
| 303 |
+
|
| 304 |
+
Primary reference artifact:
|
| 305 |
+
|
| 306 |
+
`artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json`
|
| 307 |
+
|
| 308 |
+
This canonical reference run uses `gpt-5.4` through an OpenAI-compatible Azure AI Foundry endpoint with `OPENAI_SEED=7`.
|
| 309 |
+
|
| 310 |
+
| Tier | Avg Task Grade | Avg Reward | Avg Raw Reward |
|
| 311 |
+
|------|----------------|------------|----------------|
|
| 312 |
+
| Easy | 0.8327 | 0.7845 | 0.7306 |
|
| 313 |
+
| Medium | 0.4625 | 0.4748 | 0.3435 |
|
| 314 |
+
| Hard | 0.5110 | 0.5382 | 0.4228 |
|
| 315 |
+
|
| 316 |
+
Overall canonical averages:
|
| 317 |
+
|
| 318 |
+
- Avg task grade: `0.6021`
|
| 319 |
+
- Avg reward: `0.5992`
|
| 320 |
+
- Avg raw reward: `0.4990`
|
| 321 |
+
|
| 322 |
+
Secondary open-weight comparison artifact:
|
| 323 |
+
|
| 324 |
+
- `artifacts/baselines/canonical_qwen2.5_72b_hf_seed7_manifest_2026-04-03.2.json`
|
| 325 |
+
|
| 326 |
+
This comparison run uses `Qwen/Qwen2.5-72B-Instruct` via the Hugging Face Router with `OPENAI_SEED=7`.
|
| 327 |
+
|
| 328 |
+
| Model | Avg Task Grade | Avg Reward | Avg Raw Reward |
|
| 329 |
+
|-------|----------------|------------|----------------|
|
| 330 |
+
| `gpt-5.4` | 0.6021 | 0.5992 | 0.4990 |
|
| 331 |
+
| `Qwen/Qwen2.5-72B-Instruct` | 0.4810 | 0.4994 | 0.3742 |
|
| 332 |
+
|
| 333 |
+
These numbers are reference points, not normative targets. The benchmark remains intentionally challenging on context-dependent and hard policy-review cases, and score movement should be interpreted relative to the same manifest and inference setup.
|
README.md
CHANGED
|
@@ -16,25 +16,59 @@ tags:
|
|
| 16 |
|
| 17 |
# SafeSpace: Content Moderation OpenEnv
|
| 18 |
|
| 19 |
-
SafeSpace is an OpenEnv benchmark for
|
| 20 |
|
| 21 |
-

|
| 23 |

|
| 24 |

|
| 25 |
-

|
| 26 |

|
| 27 |
|
| 28 |
-
##
|
| 29 |
|
| 30 |
-
|
| 31 |
-
- **Interface:** typed OpenEnv `step()` / `reset()` / `state()` API backed by FastAPI and a typed client
|
| 32 |
-
- **Benchmark:** 3 graded workflows, a 60-scenario canonical split, and a 367-scenario full corpus
|
| 33 |
-
- **Scoring:** trajectory shaping plus deterministic terminal grading, with no LLM judge in the loop
|
| 34 |
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
Preferred:
|
| 40 |
|
|
@@ -48,7 +82,9 @@ Alternative:
|
|
| 48 |
pip install -e ".[dev]"
|
| 49 |
```
|
| 50 |
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
```bash
|
| 54 |
scripts/preflight.sh
|
|
@@ -85,93 +121,60 @@ with SafeSpaceEnv(base_url="http://localhost:8000").sync() as env:
|
|
| 85 |
print(result.observation.task_grade)
|
| 86 |
```
|
| 87 |
|
| 88 |
-
##
|
| 89 |
-
|
| 90 |
-
```bash
|
| 91 |
-
python inference.py --validate-config
|
| 92 |
-
```
|
| 93 |
-
|
| 94 |
-
## Episode Flow
|
| 95 |
-
|
| 96 |
-

|
| 97 |
-
|
| 98 |
-
### Example Walkthrough: `med_001`
|
| 99 |
-
|
| 100 |
-
`med_001` looks like a violent threat on the surface:
|
| 101 |
-
|
| 102 |
-
> "I swear I'm going to kill you next round bro, you're dead meat"
|
| 103 |
|
| 104 |
-
|
| 105 |
|
| 106 |
-
|
| 107 |
-
2. requests `request_thread_context`
|
| 108 |
-
3. sees friendly gaming banter in the thread
|
| 109 |
-
4. submits:
|
| 110 |
|
| 111 |
-
```
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
primary_violation="none",
|
| 116 |
-
severity="none",
|
| 117 |
-
confidence=0.82,
|
| 118 |
-
key_factors=["gaming_or_competition_context", "no_violation_found"],
|
| 119 |
-
)
|
| 120 |
```
|
| 121 |
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
This is the core SafeSpace idea: the agent is rewarded not just for the final answer, but also for deciding *when* to investigate and *what* to investigate.
|
| 125 |
-
|
| 126 |
-
## Why This Is an RL Environment, Not a Classifier
|
| 127 |
-
|
| 128 |
-
A one-shot classifier sees only the post and predicts a label. Real moderation work is sequential:
|
| 129 |
-
|
| 130 |
-
- moderators inspect the post
|
| 131 |
-
- they choose which context to fetch
|
| 132 |
-
- each fetch has a cost
|
| 133 |
-
- they stop when they have enough evidence
|
| 134 |
-
- they make a decision with a level of certainty
|
| 135 |
-
|
| 136 |
-
SafeSpace turns that workflow into an RL problem. Investigation actions produce trajectory-level reward, bad investigation habits are penalized, and the terminal reward measures moderation quality, calibration, and efficiency together.
|
| 137 |
-
|
| 138 |
-
SafeSpace is designed around the parts of moderation that are hard for static classifiers:
|
| 139 |
-
|
| 140 |
-
- deciding when the surface text is enough
|
| 141 |
-
- deciding when context changes the answer
|
| 142 |
-
- handling asymmetric costs for false negatives vs. over-moderation
|
| 143 |
-
- learning when escalation is better than bluffing
|
| 144 |
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
-
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
- **Difficulty progression:** easy, medium, hard
|
| 155 |
|
| 156 |
-
##
|
| 157 |
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
| `context_dependent` | medium | 140 | One targeted context request often flips the correct answer |
|
| 162 |
-
| `policy_edge_cases` | hard | 110 | Multiple signals conflict; escalation, calibration, and precedent matter |
|
| 163 |
|
| 164 |
-
###
|
| 165 |
|
| 166 |
-
|
|
|
|
|
|
|
| 167 |
|
| 168 |
-
###
|
| 169 |
|
| 170 |
-
|
|
|
|
|
|
|
| 171 |
|
| 172 |
-
|
| 173 |
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
| 175 |
|
| 176 |
## Action Space
|
| 177 |
|
|
@@ -187,7 +190,7 @@ Each investigation action consumes one step from the episode budget.
|
|
| 187 |
| `request_similar_precedents` | prior moderation examples | policy conflict and edge-case consistency |
|
| 188 |
| `request_reporter_credibility` | reporter accuracy history | brigading or unreliable reporting |
|
| 189 |
|
| 190 |
-
|
| 191 |
|
| 192 |
```python
|
| 193 |
ModerationAction(
|
|
@@ -231,8 +234,8 @@ print(obs.gathered_context.thread_context) # None until requested
|
|
| 231 |
|
| 232 |
- `episode_id`
|
| 233 |
- `step_count`
|
| 234 |
-
- `task_id`
|
| 235 |
-
- `scenario_id`
|
| 236 |
- `difficulty`
|
| 237 |
- `trigger_type`
|
| 238 |
- `actions_taken`
|
|
@@ -240,18 +243,33 @@ print(obs.gathered_context.thread_context) # None until requested
|
|
| 240 |
- `context_requested`
|
| 241 |
- `decision_made`
|
| 242 |
- `episode_reward`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
|
| 244 |
-
|
|
|
|
|
|
|
| 245 |
|
| 246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
|
| 248 |
-
SafeSpace
|
| 249 |
|
| 250 |
-
|
| 251 |
|
| 252 |
-
|
| 253 |
|
| 254 |
-
|
| 255 |
|
| 256 |
| Event | Raw reward |
|
| 257 |
|-------|------------|
|
|
@@ -261,144 +279,93 @@ Investigation steps receive immediate feedback:
|
|
| 261 |
| invalid action | `-0.06` |
|
| 262 |
| budget exhausted before decision | `-0.15` |
|
| 263 |
|
| 264 |
-
The cumulative trajectory signal is capped at `+/-0.15`
|
| 265 |
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
When the agent takes `decide`, the final reward combines:
|
| 269 |
|
| 270 |
- decision reward
|
| 271 |
- factor overlap reward
|
| 272 |
- efficiency bonus
|
| 273 |
- calibration bonus
|
| 274 |
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
- decision correctness
|
| 278 |
-
- policy violation correctness
|
| 279 |
-
- severity correctness
|
| 280 |
-
- adjacent-decision partial credit
|
| 281 |
-
- dangerous false negatives
|
| 282 |
|
| 283 |
-
|
| 284 |
|
| 285 |
-
|
| 286 |
|
| 287 |
-
|
|
|
|
|
|
|
| 288 |
|
| 289 |
-
|
| 290 |
-
- `grade_factors()` scores cited rationale factors
|
| 291 |
-
- `compute_reward()` combines terminal moderation quality
|
| 292 |
-
- trajectory reward helpers score investigation behavior step by step
|
| 293 |
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
## Benchmark Splits and Scenario Stats
|
| 297 |
|
| 298 |
Canonical benchmark:
|
| 299 |
|
| 300 |
- Manifest version: `2026-04-03.2`
|
| 301 |
-
- Canonical split size: 60 scenarios total
|
| 302 |
-
- Canonical composition: 20 scenarios per benchmark task
|
| 303 |
- Canonical benchmark is the headline evaluation set used by `inference.py --mode canonical`
|
| 304 |
|
| 305 |
Full corpus:
|
| 306 |
|
| 307 |
-
- Total scenarios: 367
|
| 308 |
-
- Easy: 117
|
| 309 |
-
- Medium: 140
|
| 310 |
-
- Hard: 110
|
|
|
|
| 311 |
|
| 312 |
Decision distribution:
|
| 313 |
|
| 314 |
-
- Approve: 139
|
| 315 |
-
- Remove: 133
|
| 316 |
-
- Warn: 54
|
| 317 |
-
- Escalate: 41
|
| 318 |
|
| 319 |
Trigger distribution:
|
| 320 |
|
| 321 |
-
- `user_report`: 210
|
| 322 |
-
- `auto_flag`: 109
|
| 323 |
-
- `appeal`: 27
|
| 324 |
-
- `proactive_audit`: 21
|
| 325 |
|
| 326 |
Context-depth distribution:
|
| 327 |
|
| 328 |
-
- `0` context requests needed: 117
|
| 329 |
-
- `1` context request needed: 123
|
| 330 |
-
- `2` context requests needed: 108
|
| 331 |
-
- `3` context requests needed: 19
|
| 332 |
-
|
| 333 |
-
The full corpus includes targeted link, policy-conflict, satire, privacy, and coded-harassment edge cases, while the 60-scenario canonical split remains the headline benchmark for fast and stable comparison.
|
| 334 |
|
| 335 |
-
|
| 336 |
|
| 337 |
-
|
|
|
|
| 338 |
|
| 339 |
-
|
| 340 |
|
| 341 |
- uses the OpenAI client for all model calls
|
| 342 |
- works with any OpenAI-compatible endpoint exposed through `API_BASE_URL`
|
| 343 |
- prefers `HF_TOKEN` and still accepts `OPENAI_API_KEY`, `API_KEY`, or `AZURE_OPENAI_API_KEY` as fallbacks
|
| 344 |
-
- evaluates through the real `SafeSpaceEnv` client/server path
|
| 345 |
- validates the benchmark manifest before running
|
| 346 |
-
- supports deterministic `canonical` and `full` modes
|
| 347 |
- emits compact `[START]`, `[STEP]`, and `[END]` logs on stdout
|
| 348 |
-
- writes aggregate metrics
|
| 349 |
-
|
| 350 |
-
### Required environment variables
|
| 351 |
-
|
| 352 |
-
```bash
|
| 353 |
-
export API_BASE_URL="<OpenAI-compatible endpoint>"
|
| 354 |
-
export MODEL_NAME="<model-id>"
|
| 355 |
-
export HF_TOKEN="<api-key>"
|
| 356 |
-
```
|
| 357 |
-
|
| 358 |
-
Accepted credential fallbacks:
|
| 359 |
-
|
| 360 |
-
```bash
|
| 361 |
-
export OPENAI_API_KEY="<api-key>"
|
| 362 |
-
# or
|
| 363 |
-
export API_KEY="<api-key>"
|
| 364 |
-
# or
|
| 365 |
-
export AZURE_OPENAI_API_KEY="<api-key>"
|
| 366 |
-
```
|
| 367 |
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
```bash
|
| 371 |
-
export OPENAI_SEED="7"
|
| 372 |
-
export ENV_BASE_URL="http://localhost:8000"
|
| 373 |
-
export LOCAL_IMAGE_NAME="safespace:latest"
|
| 374 |
-
```
|
| 375 |
-
|
| 376 |
-
Connection precedence:
|
| 377 |
-
|
| 378 |
-
- if `--env-base-url` is passed, use that server
|
| 379 |
-
- else if `ENV_BASE_URL` is set, use that server
|
| 380 |
-
- else if `LOCAL_IMAGE_NAME` is set, launch the local Docker image through OpenEnv
|
| 381 |
-
- else fall back to `http://localhost:8000`
|
| 382 |
-
|
| 383 |
-
### Run the canonical reference baseline
|
| 384 |
-
|
| 385 |
-
```bash
|
| 386 |
-
python inference.py --mode canonical --summary-json-path artifacts/run-summary.json
|
| 387 |
-
```
|
| 388 |
|
| 389 |
-
|
|
|
|
|
|
|
| 390 |
|
| 391 |
-
|
| 392 |
-
python inference.py --validate-config
|
| 393 |
-
```
|
| 394 |
|
| 395 |
-
|
|
|
|
|
|
|
| 396 |
|
| 397 |
-
|
| 398 |
-
python inference.py --mode full --summary-json-path artifacts/run-summary.json
|
| 399 |
-
```
|
| 400 |
-
|
| 401 |
-
The script emits stdout in the following single-line format:
|
| 402 |
|
| 403 |
```text
|
| 404 |
[START] task=<task_name> env=safespace model=<model_name>
|
|
@@ -406,56 +373,42 @@ The script emits stdout in the following single-line format:
|
|
| 406 |
[END] success=<true|false> steps=<n> score=<score> rewards=<r1,r2,...,rn>
|
| 407 |
```
|
| 408 |
|
| 409 |
-
When `--summary-json-path` is set, the file records aggregate metrics, per-task breakdowns, decision distributions, runtime metadata, and failure details.
|
| 410 |
-
|
| 411 |
-
### Public score semantics
|
| 412 |
-
|
| 413 |
-
- Final episode `score` in the `[END]` line is always `task_grade`, which already lives in `[0.0, 1.0]`.
|
| 414 |
-
- Public `reward` values are normalized into `[0.0, 1.0]` for compatibility with tooling that expects normalized reward signals.
|
| 415 |
-
- Raw signed reward values are preserved in the JSON summary, state, and reward breakdown payloads for debugging and RL analysis.
|
| 416 |
-
|
| 417 |
-
### Canonical vs. full evaluation
|
| 418 |
-
|
| 419 |
-
- `canonical` evaluates a fixed 60-scenario benchmark defined in `server/data/benchmark_manifest.json`.
|
| 420 |
-
- `canonical` is the score we treat as the headline benchmark because it is fast, comparable across reruns, and stable in task composition.
|
| 421 |
-
- `full` evaluates the entire current corpus of 367 scenarios.
|
| 422 |
-
- `full` is intended as a broader stress test and regression suite; it is slower and more expensive, but gives a better picture of full-corpus generalization.
|
| 423 |
-
- `full` runs the canonical split first and then the remainder of the corpus, so `--limit-per-task` is useful for cheap smoke checks.
|
| 424 |
-
|
| 425 |
-
### Current reference baselines
|
| 426 |
-
|
| 427 |
Primary reference artifact:
|
| 428 |
|
| 429 |
`artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json`
|
| 430 |
|
| 431 |
-
This
|
| 432 |
|
| 433 |
| Task | Difficulty | Avg Task Grade | Avg Reward | Avg Raw Reward | Decision Distribution |
|
| 434 |
|------|------------|----------------|------------|----------------|----------------------|
|
| 435 |
-
| `clear_violations` | easy |
|
| 436 |
-
| `context_dependent` | medium |
|
| 437 |
-
| `policy_edge_cases` | hard |
|
| 438 |
|
| 439 |
-
|
| 440 |
|
| 441 |
-
|
|
|
|
|
|
|
|
|
|
| 442 |
|
| 443 |
-
|
| 444 |
|
| 445 |
-
|
| 446 |
|
| 447 |
-
`
|
| 448 |
-
|
| 449 |
-
This comparison run uses `Qwen/Qwen2.5-72B-Instruct` via the Hugging Face Router with `HF_TOKEN` and `OPENAI_SEED=7`.
|
| 450 |
|
| 451 |
| Model | Avg Task Grade | Avg Reward | Avg Raw Reward | Failed Episodes |
|
| 452 |
|-------|----------------|------------|----------------|-----------------|
|
| 453 |
-
| `gpt-5.4` | **0.
|
| 454 |
-
| `Qwen/Qwen2.5-72B-Instruct` | `0.
|
|
|
|
|
|
|
| 455 |
|
| 456 |
-
|
|
|
|
| 457 |
|
| 458 |
-
Run the full verification stack from the repository root
|
| 459 |
|
| 460 |
```bash
|
| 461 |
scripts/preflight.sh
|
|
@@ -488,13 +441,16 @@ openenv push --repo-id <username>/safespace
|
|
| 488 |
Submission-path hardening notes:
|
| 489 |
|
| 490 |
- the Docker build, health check, and typed-client smoke path are covered by `scripts/preflight.sh`
|
| 491 |
-
- the package asset smoke test
|
| 492 |
- the canonical evaluation path has been verified under a `2 CPU / 8 GB` container budget and completed well under the hackathon's `20` minute runtime limit
|
| 493 |
|
| 494 |
-
|
|
|
|
|
|
|
|
|
|
| 495 |
|
| 496 |
```text
|
| 497 |
-
|
| 498 |
├── artifacts/
|
| 499 |
│ ├── baselines/
|
| 500 |
│ └── readme/
|
|
@@ -507,6 +463,7 @@ content_moderation_env/
|
|
| 507 |
├── README.md
|
| 508 |
├── scripts/
|
| 509 |
│ ├── check_package_assets.py
|
|
|
|
| 510 |
│ ├── preflight.sh
|
| 511 |
│ ├── report_stats.py
|
| 512 |
│ └── validate-submission.sh
|
|
@@ -521,6 +478,8 @@ content_moderation_env/
|
|
| 521 |
└── tests/
|
| 522 |
```
|
| 523 |
|
|
|
|
|
|
|
| 524 |
## License
|
| 525 |
|
| 526 |
This project is licensed under the BSD 3-Clause License. See `LICENSE`.
|
|
|
|
| 16 |
|
| 17 |
# SafeSpace: Content Moderation OpenEnv
|
| 18 |
|
| 19 |
+
SafeSpace is an OpenEnv benchmark for sequential social-platform content moderation. Instead of making a one-shot label prediction, the agent reviews one reported post at a time, decides whether to gather more evidence under a fixed action budget, and then submits a structured moderation decision with calibrated confidence and cited factors.
|
| 20 |
|
| 21 |
+

|
| 22 |

|
| 23 |

|
| 24 |

|
|
|
|
| 25 |

|
| 26 |
|
| 27 |
+
Quick links: [HF Space](https://huggingface.co/spaces/Ishangtxl/SafeSpace) · [Run locally](#run-the-environment-locally) · [Run the reference evaluator](#run-the-reference-evaluator) · [Action Space](#action-space) · [Observation Space](#observation-space) · [Example Episode](#example-episode) · [Appendix](#appendix)
|
| 28 |
|
| 29 |
+
## Environment Contract
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
+
| Item | SafeSpace contract |
|
| 32 |
+
|------|--------------------|
|
| 33 |
+
| Episode unit | One reported content item |
|
| 34 |
+
| Budget | `8` total actions per episode |
|
| 35 |
+
| Action space | `7` investigation actions + `1` terminal `decide` action |
|
| 36 |
+
| Final decisions | `approve`, `remove`, `warn`, `escalate` |
|
| 37 |
+
| Observation | Post content, trigger info, gathered context, platform policy, citable factors, progress fields |
|
| 38 |
+
| Reward | Trajectory shaping during investigation + deterministic terminal grading |
|
| 39 |
+
| Difficulty tiers | `easy`, `medium`, `hard` |
|
| 40 |
+
| Canonical benchmark | `60` scenarios total, `20` per task |
|
| 41 |
+
| Full corpus | `367` scenarios of broader authored + procedural regression coverage |
|
| 42 |
|
| 43 |
+
## Environment Description
|
| 44 |
+
|
| 45 |
+
SafeSpace models moderation as a budgeted evidence-gathering episode over one reported post. The benchmark is designed to test whether an agent can decide when the post alone is enough, when context changes the answer, and when escalation is more appropriate than overconfident guessing.
|
| 46 |
+
|
| 47 |
+
The benchmark contains three task families:
|
| 48 |
+
|
| 49 |
+
| Task | Difficulty | Scenarios | What makes it hard |
|
| 50 |
+
|------|------------|-----------|--------------------|
|
| 51 |
+
| `clear_violations` | easy | 117 | Text alone is sufficient; extra investigation wastes reward |
|
| 52 |
+
| `context_dependent` | medium | 140 | One targeted context request often flips the correct decision |
|
| 53 |
+
| `policy_edge_cases` | hard | 110 | Multiple signals conflict; calibration, precedent, and escalation matter |
|
| 54 |
+
|
| 55 |
+
## Connect To The Deployed Space
|
| 56 |
+
|
| 57 |
+
Space page: [Ishangtxl/SafeSpace](https://huggingface.co/spaces/Ishangtxl/SafeSpace)
|
| 58 |
+
|
| 59 |
+
Programmatic endpoint:
|
| 60 |
+
|
| 61 |
+
```python
|
| 62 |
+
from content_moderation_env import SafeSpaceEnv
|
| 63 |
+
|
| 64 |
+
with SafeSpaceEnv(base_url="https://ishangtxl-safespace.hf.space").sync() as env:
|
| 65 |
+
result = env.reset()
|
| 66 |
+
print(result.observation.content_item.text)
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
## Run The Environment Locally
|
| 70 |
+
|
| 71 |
+
### 1. Install dependencies
|
| 72 |
|
| 73 |
Preferred:
|
| 74 |
|
|
|
|
| 82 |
pip install -e ".[dev]"
|
| 83 |
```
|
| 84 |
|
| 85 |
+
SafeSpace depends on `openenv-core[core]>=0.2.3,<0.3`.
|
| 86 |
+
|
| 87 |
+
### 2. Run the local preflight
|
| 88 |
|
| 89 |
```bash
|
| 90 |
scripts/preflight.sh
|
|
|
|
| 121 |
print(result.observation.task_grade)
|
| 122 |
```
|
| 123 |
|
| 124 |
+
## Run The Reference Evaluator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
+
`inference.py` is the shipped reference evaluator. It uses the real `SafeSpaceEnv` client/server path and supports deterministic `canonical` and `full` evaluation modes.
|
| 127 |
|
| 128 |
+
### Required environment variables
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
```bash
|
| 131 |
+
export API_BASE_URL="<OpenAI-compatible endpoint>"
|
| 132 |
+
export MODEL_NAME="<model-id>"
|
| 133 |
+
export HF_TOKEN="<api-key>"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
```
|
| 135 |
|
| 136 |
+
Accepted credential fallbacks:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
+
```bash
|
| 139 |
+
export OPENAI_API_KEY="<api-key>"
|
| 140 |
+
# or
|
| 141 |
+
export API_KEY="<api-key>"
|
| 142 |
+
# or
|
| 143 |
+
export AZURE_OPENAI_API_KEY="<api-key>"
|
| 144 |
+
```
|
| 145 |
|
| 146 |
+
Additional optional variables:
|
| 147 |
|
| 148 |
+
```bash
|
| 149 |
+
export OPENAI_SEED="7"
|
| 150 |
+
export ENV_BASE_URL="http://localhost:8000"
|
| 151 |
+
export LOCAL_IMAGE_NAME="safespace:latest"
|
| 152 |
+
```
|
|
|
|
| 153 |
|
| 154 |
+
### Validate evaluator config
|
| 155 |
|
| 156 |
+
```bash
|
| 157 |
+
python inference.py --validate-config
|
| 158 |
+
```
|
|
|
|
|
|
|
| 159 |
|
| 160 |
+
### Run the canonical benchmark
|
| 161 |
|
| 162 |
+
```bash
|
| 163 |
+
python inference.py --mode canonical --summary-json-path artifacts/run-summary.json
|
| 164 |
+
```
|
| 165 |
|
| 166 |
+
### Run the full corpus evaluation
|
| 167 |
|
| 168 |
+
```bash
|
| 169 |
+
python inference.py --mode full --summary-json-path artifacts/run-summary.json
|
| 170 |
+
```
|
| 171 |
|
| 172 |
+
Connection precedence:
|
| 173 |
|
| 174 |
+
- if `--env-base-url` is passed, use that server
|
| 175 |
+
- else if `ENV_BASE_URL` is set, use that server
|
| 176 |
+
- else if `LOCAL_IMAGE_NAME` is set, launch the local Docker image through OpenEnv
|
| 177 |
+
- else fall back to `http://localhost:8000`
|
| 178 |
|
| 179 |
## Action Space
|
| 180 |
|
|
|
|
| 190 |
| `request_similar_precedents` | prior moderation examples | policy conflict and edge-case consistency |
|
| 191 |
| `request_reporter_credibility` | reporter accuracy history | brigading or unreliable reporting |
|
| 192 |
|
| 193 |
+
Terminal action:
|
| 194 |
|
| 195 |
```python
|
| 196 |
ModerationAction(
|
|
|
|
| 234 |
|
| 235 |
- `episode_id`
|
| 236 |
- `step_count`
|
| 237 |
+
- `task_id`
|
| 238 |
+
- `scenario_id`
|
| 239 |
- `difficulty`
|
| 240 |
- `trigger_type`
|
| 241 |
- `actions_taken`
|
|
|
|
| 243 |
- `context_requested`
|
| 244 |
- `decision_made`
|
| 245 |
- `episode_reward`
|
| 246 |
+
- `raw_episode_reward`
|
| 247 |
+
- `done`
|
| 248 |
+
- `last_error_code`
|
| 249 |
+
|
| 250 |
+
The public HTTP `/schema` and `/state` endpoints expose the typed `ModerationState` contract directly. The session-backed `SafeSpaceEnv` client remains the canonical benchmark path for live per-episode evaluation.
|
| 251 |
+
|
| 252 |
+
## Example Episode
|
| 253 |
+
|
| 254 |
+
`med_001` looks like a violent threat on the surface:
|
| 255 |
|
| 256 |
+
> "I swear I'm going to kill you next round bro, you're dead meat"
|
| 257 |
+
|
| 258 |
+
The correct policy is not obvious from the text alone, so a strong agent typically:
|
| 259 |
|
| 260 |
+
1. calls `reset(scenario_id="med_001")`
|
| 261 |
+
2. requests `request_thread_context`
|
| 262 |
+
3. sees friendly gaming banter in the thread
|
| 263 |
+
4. submits an `approve` decision with `primary_violation="none"` and factors such as `gaming_or_competition_context`
|
| 264 |
+
5. receives both a terminal reward breakdown and a normalized task grade
|
| 265 |
|
| 266 |
+
This is the core SafeSpace idea: the agent is rewarded not just for the final answer, but also for deciding when to investigate and what to investigate.
|
| 267 |
|
| 268 |
+
## Reward And Grading
|
| 269 |
|
| 270 |
+
SafeSpace optimizes moderation quality first, then explanation quality, efficiency, and calibration.
|
| 271 |
|
| 272 |
+
Trajectory shaping:
|
| 273 |
|
| 274 |
| Event | Raw reward |
|
| 275 |
|-------|------------|
|
|
|
|
| 279 |
| invalid action | `-0.06` |
|
| 280 |
| budget exhausted before decision | `-0.15` |
|
| 281 |
|
| 282 |
+
The cumulative trajectory signal is capped at `+/-0.15`.
|
| 283 |
|
| 284 |
+
Terminal reward combines:
|
|
|
|
|
|
|
| 285 |
|
| 286 |
- decision reward
|
| 287 |
- factor overlap reward
|
| 288 |
- efficiency bonus
|
| 289 |
- calibration bonus
|
| 290 |
|
| 291 |
+
All grading is deterministic and programmatic. There are no LLM judges inside the environment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
|
| 293 |
+
## Research Grounding
|
| 294 |
|
| 295 |
+
SafeSpace is informed by prior content-moderation and explainability research, including HateXplain, especially around rationale-grounded moderation decisions, ambiguity, and explanation quality. We do not claim direct reuse of HateXplain samples in the current shipped scenario corpus.
|
| 296 |
|
| 297 |
+
- [OpenEnv documentation](https://meta-pytorch.org/OpenEnv/) and the [OpenEnv Quick Start](https://meta-pytorch.org/OpenEnv/auto_getting_started/) describe the environment interface conventions that SafeSpace follows.
|
| 298 |
+
- [HateXplain: A Benchmark Dataset for Explainable Hate Speech Detection](https://arxiv.org/abs/2012.10289) motivates rationale-aware moderation evaluation and explainability-oriented supervision.
|
| 299 |
+
- [Content moderation on social media: Does it matter who and why moderates hate speech?](https://scholars.cityu.edu.hk/en/publications/content-moderation-on-social-media-does-it-matter-who-and-why-mod/) is relevant to moderation transparency, trust, and explanation framing.
|
| 300 |
|
| 301 |
+
## Appendix
|
|
|
|
|
|
|
|
|
|
| 302 |
|
| 303 |
+
<details>
|
| 304 |
+
<summary><strong>Benchmark splits and corpus statistics</strong></summary>
|
|
|
|
| 305 |
|
| 306 |
Canonical benchmark:
|
| 307 |
|
| 308 |
- Manifest version: `2026-04-03.2`
|
| 309 |
+
- Canonical split size: `60` scenarios total
|
| 310 |
+
- Canonical composition: `20` scenarios per benchmark task
|
| 311 |
- Canonical benchmark is the headline evaluation set used by `inference.py --mode canonical`
|
| 312 |
|
| 313 |
Full corpus:
|
| 314 |
|
| 315 |
+
- Total scenarios: `367`
|
| 316 |
+
- Easy: `117`
|
| 317 |
+
- Medium: `140`
|
| 318 |
+
- Hard: `110`
|
| 319 |
+
- Includes broader authored extensions plus procedural stress/regression coverage outside the official canonical benchmark
|
| 320 |
|
| 321 |
Decision distribution:
|
| 322 |
|
| 323 |
+
- Approve: `139`
|
| 324 |
+
- Remove: `133`
|
| 325 |
+
- Warn: `54`
|
| 326 |
+
- Escalate: `41`
|
| 327 |
|
| 328 |
Trigger distribution:
|
| 329 |
|
| 330 |
+
- `user_report`: `210`
|
| 331 |
+
- `auto_flag`: `109`
|
| 332 |
+
- `appeal`: `27`
|
| 333 |
+
- `proactive_audit`: `21`
|
| 334 |
|
| 335 |
Context-depth distribution:
|
| 336 |
|
| 337 |
+
- `0` context requests needed: `117`
|
| 338 |
+
- `1` context request needed: `123`
|
| 339 |
+
- `2` context requests needed: `108`
|
| 340 |
+
- `3` context requests needed: `19`
|
|
|
|
|
|
|
| 341 |
|
| 342 |
+
</details>
|
| 343 |
|
| 344 |
+
<details>
|
| 345 |
+
<summary><strong>Reference evaluation details and baseline results</strong></summary>
|
| 346 |
|
| 347 |
+
`inference.py`:
|
| 348 |
|
| 349 |
- uses the OpenAI client for all model calls
|
| 350 |
- works with any OpenAI-compatible endpoint exposed through `API_BASE_URL`
|
| 351 |
- prefers `HF_TOKEN` and still accepts `OPENAI_API_KEY`, `API_KEY`, or `AZURE_OPENAI_API_KEY` as fallbacks
|
|
|
|
| 352 |
- validates the benchmark manifest before running
|
|
|
|
| 353 |
- emits compact `[START]`, `[STEP]`, and `[END]` logs on stdout
|
| 354 |
+
- writes aggregate metrics when `--summary-json-path` is provided
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
|
| 356 |
+
Public score semantics:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
|
| 358 |
+
- Final episode `score` in the `[END]` line is always `task_grade`, which lives in `[0.0, 1.0]`
|
| 359 |
+
- Public `reward` values are normalized into `[0.0, 1.0]`
|
| 360 |
+
- Raw signed reward values are preserved in the JSON summary, state, and reward breakdown payloads
|
| 361 |
|
| 362 |
+
Canonical vs. full:
|
|
|
|
|
|
|
| 363 |
|
| 364 |
+
- `canonical` evaluates the fixed 60-scenario benchmark in `server/data/benchmark_manifest.json`
|
| 365 |
+
- `full` evaluates the entire current corpus of 367 scenarios
|
| 366 |
+
- `full` runs the canonical split first and then the remainder of the corpus
|
| 367 |
|
| 368 |
+
The evaluator emits stdout in the following single-line format:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
|
| 370 |
```text
|
| 371 |
[START] task=<task_name> env=safespace model=<model_name>
|
|
|
|
| 373 |
[END] success=<true|false> steps=<n> score=<score> rewards=<r1,r2,...,rn>
|
| 374 |
```
|
| 375 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
Primary reference artifact:
|
| 377 |
|
| 378 |
`artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json`
|
| 379 |
|
| 380 |
+
This canonical reference run uses `gpt-5.4` through an OpenAI-compatible Azure AI Foundry endpoint with `OPENAI_SEED=7`.
|
| 381 |
|
| 382 |
| Task | Difficulty | Avg Task Grade | Avg Reward | Avg Raw Reward | Decision Distribution |
|
| 383 |
|------|------------|----------------|------------|----------------|----------------------|
|
| 384 |
+
| `clear_violations` | easy | `0.8327` | `0.7845` | `0.7306` | remove: 10, approve: 9, warn: 1 |
|
| 385 |
+
| `context_dependent` | medium | `0.4625` | `0.4748` | `0.3435` | approve: 10, warn: 6, remove: 4 |
|
| 386 |
+
| `policy_edge_cases` | hard | `0.5110` | `0.5382` | `0.4228` | escalate: 7, approve: 7, warn: 3, remove: 3 |
|
| 387 |
|
| 388 |
+
Overall:
|
| 389 |
|
| 390 |
+
- Avg task grade: `0.6021`
|
| 391 |
+
- Avg reward: `0.5992`
|
| 392 |
+
- Avg raw reward: `0.4990`
|
| 393 |
+
- Failed episodes: `0`
|
| 394 |
|
| 395 |
+
Secondary open-weight comparison artifact:
|
| 396 |
|
| 397 |
+
- `artifacts/baselines/canonical_qwen2.5_72b_hf_seed7_manifest_2026-04-03.2.json`
|
| 398 |
|
| 399 |
+
This comparison run uses `Qwen/Qwen2.5-72B-Instruct` via the Hugging Face Router with `OPENAI_SEED=7`.
|
|
|
|
|
|
|
| 400 |
|
| 401 |
| Model | Avg Task Grade | Avg Reward | Avg Raw Reward | Failed Episodes |
|
| 402 |
|-------|----------------|------------|----------------|-----------------|
|
| 403 |
+
| `gpt-5.4` | **`0.6021`** | `0.5992` | `0.4990` | `0` |
|
| 404 |
+
| `Qwen/Qwen2.5-72B-Instruct` | `0.4810` | `0.4994` | `0.3742` | `0` |
|
| 405 |
+
|
| 406 |
+
</details>
|
| 407 |
|
| 408 |
+
<details>
|
| 409 |
+
<summary><strong>Validation and deployment</strong></summary>
|
| 410 |
|
| 411 |
+
Run the full verification stack from the repository root:
|
| 412 |
|
| 413 |
```bash
|
| 414 |
scripts/preflight.sh
|
|
|
|
| 441 |
Submission-path hardening notes:
|
| 442 |
|
| 443 |
- the Docker build, health check, and typed-client smoke path are covered by `scripts/preflight.sh`
|
| 444 |
+
- the package asset smoke test self-heals `pip` with `ensurepip` if the active interpreter does not expose `python -m pip`
|
| 445 |
- the canonical evaluation path has been verified under a `2 CPU / 8 GB` container budget and completed well under the hackathon's `20` minute runtime limit
|
| 446 |
|
| 447 |
+
</details>
|
| 448 |
+
|
| 449 |
+
<details>
|
| 450 |
+
<summary><strong>Project layout</strong></summary>
|
| 451 |
|
| 452 |
```text
|
| 453 |
+
SafeSpace_Env/
|
| 454 |
├── artifacts/
|
| 455 |
│ ├── baselines/
|
| 456 |
│ └── readme/
|
|
|
|
| 463 |
├── README.md
|
| 464 |
├── scripts/
|
| 465 |
│ ├── check_package_assets.py
|
| 466 |
+
│ ├── generate_scenarios.py
|
| 467 |
│ ├── preflight.sh
|
| 468 |
│ ├── report_stats.py
|
| 469 |
│ └── validate-submission.sh
|
|
|
|
| 478 |
└── tests/
|
| 479 |
```
|
| 480 |
|
| 481 |
+
</details>
|
| 482 |
+
|
| 483 |
## License
|
| 484 |
|
| 485 |
This project is licensed under the BSD 3-Clause License. See `LICENSE`.
|
artifacts/baselines/canonical_gpt-5.4_azure_seed7_manifest_2026-04-03.2.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
artifacts/baselines/canonical_qwen2.5_72b_hf_seed7_manifest_2026-04-03.2.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
inference.py
CHANGED
|
@@ -1663,7 +1663,9 @@ async def _async_main(args: argparse.Namespace) -> None:
|
|
| 1663 |
failure_details: List[Dict[str, Any]] = []
|
| 1664 |
|
| 1665 |
client = await create_env_client(args.env_base_url)
|
| 1666 |
-
|
|
|
|
|
|
|
| 1667 |
for task_id in TASK_TO_DIFFICULTY:
|
| 1668 |
scenario_ids = load_scenario_ids(task_id, args.mode)
|
| 1669 |
if args.limit_per_task is not None:
|
|
@@ -1676,6 +1678,12 @@ async def _async_main(args: argparse.Namespace) -> None:
|
|
| 1676 |
)
|
| 1677 |
task_summaries[task_id] = task_summary
|
| 1678 |
failure_details.extend(task_failures)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1679 |
|
| 1680 |
total_scenarios = sum(
|
| 1681 |
summary["num_scenarios"] for summary in task_summaries.values()
|
|
|
|
| 1663 |
failure_details: List[Dict[str, Any]] = []
|
| 1664 |
|
| 1665 |
client = await create_env_client(args.env_base_url)
|
| 1666 |
+
try:
|
| 1667 |
+
if hasattr(client, "connect"):
|
| 1668 |
+
await client.connect()
|
| 1669 |
for task_id in TASK_TO_DIFFICULTY:
|
| 1670 |
scenario_ids = load_scenario_ids(task_id, args.mode)
|
| 1671 |
if args.limit_per_task is not None:
|
|
|
|
| 1678 |
)
|
| 1679 |
task_summaries[task_id] = task_summary
|
| 1680 |
failure_details.extend(task_failures)
|
| 1681 |
+
finally:
|
| 1682 |
+
try:
|
| 1683 |
+
if hasattr(client, "close"):
|
| 1684 |
+
await client.close()
|
| 1685 |
+
except Exception:
|
| 1686 |
+
pass
|
| 1687 |
|
| 1688 |
total_scenarios = sum(
|
| 1689 |
summary["num_scenarios"] for summary in task_summaries.values()
|
server/data/scenarios_easy.json
CHANGED
|
@@ -5721,9 +5721,9 @@
|
|
| 5721 |
"category": "obvious_spam",
|
| 5722 |
"content_item": {
|
| 5723 |
"post_id": "p_83740",
|
| 5724 |
-
"text": "
|
| 5725 |
-
"author_id": "
|
| 5726 |
-
"community": "
|
| 5727 |
"timestamp": "2026-02-26T13:57:00Z",
|
| 5728 |
"media_type": "text",
|
| 5729 |
"media_description": null
|
|
@@ -5739,20 +5739,19 @@
|
|
| 5739 |
},
|
| 5740 |
"available_context": {
|
| 5741 |
"author_profile": {
|
| 5742 |
-
"bio": "
|
| 5743 |
-
"account_age_days":
|
| 5744 |
-
"follower_count":
|
| 5745 |
-
"post_count":
|
| 5746 |
"communities": [
|
| 5747 |
-
"
|
| 5748 |
-
"
|
| 5749 |
-
"
|
| 5750 |
-
"books"
|
| 5751 |
]
|
| 5752 |
},
|
| 5753 |
"author_violations": [],
|
| 5754 |
"thread_context": null,
|
| 5755 |
-
"community_rules": "
|
| 5756 |
"linked_content_summary": null,
|
| 5757 |
"similar_precedents": null,
|
| 5758 |
"reporter_credibility": null
|
|
@@ -5766,7 +5765,7 @@
|
|
| 5766 |
"clear_violation_no_exception"
|
| 5767 |
],
|
| 5768 |
"context_needed": [],
|
| 5769 |
-
"explanation": "
|
| 5770 |
}
|
| 5771 |
},
|
| 5772 |
{
|
|
@@ -5775,9 +5774,9 @@
|
|
| 5775 |
"category": "obvious_spam",
|
| 5776 |
"content_item": {
|
| 5777 |
"post_id": "p_84444",
|
| 5778 |
-
"text": "
|
| 5779 |
-
"author_id": "
|
| 5780 |
-
"community": "
|
| 5781 |
"timestamp": "2026-02-26T21:08:00Z",
|
| 5782 |
"media_type": "text",
|
| 5783 |
"media_description": null
|
|
@@ -5793,20 +5792,19 @@
|
|
| 5793 |
},
|
| 5794 |
"available_context": {
|
| 5795 |
"author_profile": {
|
| 5796 |
-
"bio": "
|
| 5797 |
-
"account_age_days":
|
| 5798 |
-
"follower_count":
|
| 5799 |
-
"post_count":
|
| 5800 |
"communities": [
|
| 5801 |
-
"
|
| 5802 |
-
"
|
| 5803 |
-
"
|
| 5804 |
-
"sports"
|
| 5805 |
]
|
| 5806 |
},
|
| 5807 |
"author_violations": [],
|
| 5808 |
"thread_context": null,
|
| 5809 |
-
"community_rules": "
|
| 5810 |
"linked_content_summary": null,
|
| 5811 |
"similar_precedents": null,
|
| 5812 |
"reporter_credibility": null
|
|
@@ -5820,7 +5818,7 @@
|
|
| 5820 |
"clear_violation_no_exception"
|
| 5821 |
],
|
| 5822 |
"context_needed": [],
|
| 5823 |
-
"explanation": "
|
| 5824 |
}
|
| 5825 |
},
|
| 5826 |
{
|
|
@@ -5880,9 +5878,9 @@
|
|
| 5880 |
"category": "obvious_spam",
|
| 5881 |
"content_item": {
|
| 5882 |
"post_id": "p_61643",
|
| 5883 |
-
"text": "
|
| 5884 |
-
"author_id": "
|
| 5885 |
-
"community": "
|
| 5886 |
"timestamp": "2026-03-06T07:52:00Z",
|
| 5887 |
"media_type": "text",
|
| 5888 |
"media_description": null
|
|
@@ -5898,20 +5896,18 @@
|
|
| 5898 |
},
|
| 5899 |
"available_context": {
|
| 5900 |
"author_profile": {
|
| 5901 |
-
"bio": "
|
| 5902 |
-
"account_age_days":
|
| 5903 |
-
"follower_count":
|
| 5904 |
-
"post_count":
|
| 5905 |
"communities": [
|
| 5906 |
-
"
|
| 5907 |
-
"
|
| 5908 |
-
"music",
|
| 5909 |
-
"travel"
|
| 5910 |
]
|
| 5911 |
},
|
| 5912 |
"author_violations": [],
|
| 5913 |
"thread_context": null,
|
| 5914 |
-
"community_rules": "
|
| 5915 |
"linked_content_summary": null,
|
| 5916 |
"similar_precedents": null,
|
| 5917 |
"reporter_credibility": null
|
|
@@ -5925,7 +5921,7 @@
|
|
| 5925 |
"clear_violation_no_exception"
|
| 5926 |
],
|
| 5927 |
"context_needed": [],
|
| 5928 |
-
"explanation": "
|
| 5929 |
}
|
| 5930 |
},
|
| 5931 |
{
|
|
@@ -5934,9 +5930,9 @@
|
|
| 5934 |
"category": "obvious_spam",
|
| 5935 |
"content_item": {
|
| 5936 |
"post_id": "p_92342",
|
| 5937 |
-
"text": "
|
| 5938 |
-
"author_id": "
|
| 5939 |
-
"community": "
|
| 5940 |
"timestamp": "2026-02-28T22:22:00Z",
|
| 5941 |
"media_type": "text",
|
| 5942 |
"media_description": null
|
|
@@ -5952,17 +5948,18 @@
|
|
| 5952 |
},
|
| 5953 |
"available_context": {
|
| 5954 |
"author_profile": {
|
| 5955 |
-
"bio": "
|
| 5956 |
-
"account_age_days":
|
| 5957 |
-
"follower_count":
|
| 5958 |
-
"post_count":
|
| 5959 |
"communities": [
|
| 5960 |
-
"
|
|
|
|
| 5961 |
]
|
| 5962 |
},
|
| 5963 |
"author_violations": [],
|
| 5964 |
"thread_context": null,
|
| 5965 |
-
"community_rules": "
|
| 5966 |
"linked_content_summary": null,
|
| 5967 |
"similar_precedents": null,
|
| 5968 |
"reporter_credibility": null
|
|
@@ -5976,7 +5973,7 @@
|
|
| 5976 |
"clear_violation_no_exception"
|
| 5977 |
],
|
| 5978 |
"context_needed": [],
|
| 5979 |
-
"explanation": "
|
| 5980 |
}
|
| 5981 |
},
|
| 5982 |
{
|
|
@@ -6257,9 +6254,9 @@
|
|
| 6257 |
"category": "false_positive_metaphor",
|
| 6258 |
"content_item": {
|
| 6259 |
"post_id": "p_56101",
|
| 6260 |
-
"text": "This new album absolutely
|
| 6261 |
-
"author_id": "
|
| 6262 |
-
"community": "
|
| 6263 |
"timestamp": "2026-03-13T17:12:00Z",
|
| 6264 |
"media_type": "text",
|
| 6265 |
"media_description": null
|
|
@@ -6275,14 +6272,13 @@
|
|
| 6275 |
},
|
| 6276 |
"available_context": {
|
| 6277 |
"author_profile": {
|
| 6278 |
-
"bio": "
|
| 6279 |
"account_age_days": 725,
|
| 6280 |
-
"follower_count":
|
| 6281 |
-
"post_count":
|
| 6282 |
"communities": [
|
| 6283 |
-
"
|
| 6284 |
-
"
|
| 6285 |
-
"crypto"
|
| 6286 |
]
|
| 6287 |
},
|
| 6288 |
"author_violations": [],
|
|
@@ -6302,7 +6298,7 @@
|
|
| 6302 |
"auto_flag_low_confidence"
|
| 6303 |
],
|
| 6304 |
"context_needed": [],
|
| 6305 |
-
"explanation": "
|
| 6306 |
}
|
| 6307 |
},
|
| 6308 |
{
|
|
@@ -6311,9 +6307,9 @@
|
|
| 6311 |
"category": "false_positive_metaphor",
|
| 6312 |
"content_item": {
|
| 6313 |
"post_id": "p_94097",
|
| 6314 |
-
"text": "
|
| 6315 |
-
"author_id": "
|
| 6316 |
-
"community": "
|
| 6317 |
"timestamp": "2026-02-28T22:45:00Z",
|
| 6318 |
"media_type": "text",
|
| 6319 |
"media_description": null
|
|
@@ -6329,13 +6325,13 @@
|
|
| 6329 |
},
|
| 6330 |
"available_context": {
|
| 6331 |
"author_profile": {
|
| 6332 |
-
"bio": "
|
| 6333 |
"account_age_days": 316,
|
| 6334 |
-
"follower_count":
|
| 6335 |
-
"post_count":
|
| 6336 |
"communities": [
|
| 6337 |
-
"
|
| 6338 |
-
"
|
| 6339 |
]
|
| 6340 |
},
|
| 6341 |
"author_violations": [],
|
|
@@ -6355,7 +6351,7 @@
|
|
| 6355 |
"auto_flag_low_confidence"
|
| 6356 |
],
|
| 6357 |
"context_needed": [],
|
| 6358 |
-
"explanation": "
|
| 6359 |
}
|
| 6360 |
},
|
| 6361 |
{
|
|
@@ -6364,9 +6360,9 @@
|
|
| 6364 |
"category": "false_positive_metaphor",
|
| 6365 |
"content_item": {
|
| 6366 |
"post_id": "p_49881",
|
| 6367 |
-
"text": "I'm dying to try that
|
| 6368 |
-
"author_id": "
|
| 6369 |
-
"community": "
|
| 6370 |
"timestamp": "2026-03-06T04:25:00Z",
|
| 6371 |
"media_type": "text",
|
| 6372 |
"media_description": null
|
|
@@ -6382,15 +6378,13 @@
|
|
| 6382 |
},
|
| 6383 |
"available_context": {
|
| 6384 |
"author_profile": {
|
| 6385 |
-
"bio": "
|
| 6386 |
"account_age_days": 784,
|
| 6387 |
-
"follower_count":
|
| 6388 |
-
"post_count":
|
| 6389 |
"communities": [
|
| 6390 |
-
"
|
| 6391 |
-
"
|
| 6392 |
-
"finance",
|
| 6393 |
-
"music"
|
| 6394 |
]
|
| 6395 |
},
|
| 6396 |
"author_violations": [],
|
|
@@ -6410,7 +6404,7 @@
|
|
| 6410 |
"auto_flag_low_confidence"
|
| 6411 |
],
|
| 6412 |
"context_needed": [],
|
| 6413 |
-
"explanation": "
|
| 6414 |
}
|
| 6415 |
},
|
| 6416 |
{
|
|
@@ -6419,9 +6413,9 @@
|
|
| 6419 |
"category": "false_positive_metaphor",
|
| 6420 |
"content_item": {
|
| 6421 |
"post_id": "p_92199",
|
| 6422 |
-
"text": "This
|
| 6423 |
-
"author_id": "
|
| 6424 |
-
"community": "
|
| 6425 |
"timestamp": "2026-03-12T15:50:00Z",
|
| 6426 |
"media_type": "text",
|
| 6427 |
"media_description": null
|
|
@@ -6437,12 +6431,13 @@
|
|
| 6437 |
},
|
| 6438 |
"available_context": {
|
| 6439 |
"author_profile": {
|
| 6440 |
-
"bio": "
|
| 6441 |
"account_age_days": 435,
|
| 6442 |
-
"follower_count":
|
| 6443 |
-
"post_count":
|
| 6444 |
"communities": [
|
| 6445 |
-
"
|
|
|
|
| 6446 |
]
|
| 6447 |
},
|
| 6448 |
"author_violations": [],
|
|
@@ -6462,7 +6457,7 @@
|
|
| 6462 |
"auto_flag_low_confidence"
|
| 6463 |
],
|
| 6464 |
"context_needed": [],
|
| 6465 |
-
"explanation": "
|
| 6466 |
}
|
| 6467 |
},
|
| 6468 |
{
|
|
@@ -6471,9 +6466,9 @@
|
|
| 6471 |
"category": "false_positive_metaphor",
|
| 6472 |
"content_item": {
|
| 6473 |
"post_id": "p_85354",
|
| 6474 |
-
"text": "The
|
| 6475 |
-
"author_id": "
|
| 6476 |
-
"community": "
|
| 6477 |
"timestamp": "2026-03-03T13:12:00Z",
|
| 6478 |
"media_type": "text",
|
| 6479 |
"media_description": null
|
|
@@ -6489,13 +6484,13 @@
|
|
| 6489 |
},
|
| 6490 |
"available_context": {
|
| 6491 |
"author_profile": {
|
| 6492 |
-
"bio": "
|
| 6493 |
"account_age_days": 427,
|
| 6494 |
-
"follower_count":
|
| 6495 |
-
"post_count":
|
| 6496 |
"communities": [
|
| 6497 |
-
"
|
| 6498 |
-
"
|
| 6499 |
]
|
| 6500 |
},
|
| 6501 |
"author_violations": [],
|
|
@@ -6515,7 +6510,7 @@
|
|
| 6515 |
"auto_flag_low_confidence"
|
| 6516 |
],
|
| 6517 |
"context_needed": [],
|
| 6518 |
-
"explanation": "
|
| 6519 |
}
|
| 6520 |
},
|
| 6521 |
{
|
|
@@ -6907,12 +6902,12 @@
|
|
| 6907 |
"category": "scam_link",
|
| 6908 |
"content_item": {
|
| 6909 |
"post_id": "p_98147",
|
| 6910 |
-
"text": "
|
| 6911 |
-
"author_id": "
|
| 6912 |
-
"community": "
|
| 6913 |
"timestamp": "2026-03-01T15:57:00Z",
|
| 6914 |
-
"media_type": "text",
|
| 6915 |
-
"media_description":
|
| 6916 |
},
|
| 6917 |
"trigger_info": {
|
| 6918 |
"trigger_type": "auto_flag",
|
|
@@ -6925,19 +6920,18 @@
|
|
| 6925 |
},
|
| 6926 |
"available_context": {
|
| 6927 |
"author_profile": {
|
| 6928 |
-
"bio": "
|
| 6929 |
-
"account_age_days":
|
| 6930 |
-
"follower_count":
|
| 6931 |
-
"post_count":
|
| 6932 |
"communities": [
|
| 6933 |
-
"
|
| 6934 |
-
"
|
| 6935 |
-
"todayilearned"
|
| 6936 |
]
|
| 6937 |
},
|
| 6938 |
"author_violations": [],
|
| 6939 |
"thread_context": null,
|
| 6940 |
-
"community_rules": "
|
| 6941 |
"linked_content_summary": null,
|
| 6942 |
"similar_precedents": null,
|
| 6943 |
"reporter_credibility": null
|
|
@@ -6952,7 +6946,7 @@
|
|
| 6952 |
"clear_violation_no_exception"
|
| 6953 |
],
|
| 6954 |
"context_needed": [],
|
| 6955 |
-
"explanation": "
|
| 6956 |
}
|
| 6957 |
},
|
| 6958 |
{
|
|
@@ -7015,12 +7009,12 @@
|
|
| 7015 |
"category": "scam_link",
|
| 7016 |
"content_item": {
|
| 7017 |
"post_id": "p_99088",
|
| 7018 |
-
"text": "
|
| 7019 |
-
"author_id": "
|
| 7020 |
-
"community": "
|
| 7021 |
"timestamp": "2026-03-01T23:35:00Z",
|
| 7022 |
-
"media_type": "text",
|
| 7023 |
-
"media_description":
|
| 7024 |
},
|
| 7025 |
"trigger_info": {
|
| 7026 |
"trigger_type": "auto_flag",
|
|
@@ -7033,18 +7027,18 @@
|
|
| 7033 |
},
|
| 7034 |
"available_context": {
|
| 7035 |
"author_profile": {
|
| 7036 |
-
"bio": "
|
| 7037 |
-
"account_age_days":
|
| 7038 |
-
"follower_count":
|
| 7039 |
-
"post_count":
|
| 7040 |
"communities": [
|
| 7041 |
-
"
|
| 7042 |
-
"
|
| 7043 |
]
|
| 7044 |
},
|
| 7045 |
"author_violations": [],
|
| 7046 |
"thread_context": null,
|
| 7047 |
-
"community_rules": "
|
| 7048 |
"linked_content_summary": null,
|
| 7049 |
"similar_precedents": null,
|
| 7050 |
"reporter_credibility": null
|
|
@@ -7059,7 +7053,7 @@
|
|
| 7059 |
"clear_violation_no_exception"
|
| 7060 |
],
|
| 7061 |
"context_needed": [],
|
| 7062 |
-
"explanation": "
|
| 7063 |
}
|
| 7064 |
},
|
| 7065 |
{
|
|
@@ -7068,12 +7062,12 @@
|
|
| 7068 |
"category": "scam_link",
|
| 7069 |
"content_item": {
|
| 7070 |
"post_id": "p_31273",
|
| 7071 |
-
"text": "
|
| 7072 |
-
"author_id": "
|
| 7073 |
-
"community": "
|
| 7074 |
"timestamp": "2026-02-13T09:03:00Z",
|
| 7075 |
-
"media_type": "text",
|
| 7076 |
-
"media_description":
|
| 7077 |
},
|
| 7078 |
"trigger_info": {
|
| 7079 |
"trigger_type": "auto_flag",
|
|
@@ -7086,17 +7080,18 @@
|
|
| 7086 |
},
|
| 7087 |
"available_context": {
|
| 7088 |
"author_profile": {
|
| 7089 |
-
"bio": "
|
| 7090 |
-
"account_age_days":
|
| 7091 |
-
"follower_count":
|
| 7092 |
-
"post_count":
|
| 7093 |
"communities": [
|
| 7094 |
-
"
|
|
|
|
| 7095 |
]
|
| 7096 |
},
|
| 7097 |
"author_violations": [],
|
| 7098 |
"thread_context": null,
|
| 7099 |
-
"community_rules": "
|
| 7100 |
"linked_content_summary": null,
|
| 7101 |
"similar_precedents": null,
|
| 7102 |
"reporter_credibility": null
|
|
@@ -7111,7 +7106,7 @@
|
|
| 7111 |
"clear_violation_no_exception"
|
| 7112 |
],
|
| 7113 |
"context_needed": [],
|
| 7114 |
-
"explanation": "
|
| 7115 |
}
|
| 7116 |
},
|
| 7117 |
{
|
|
@@ -7120,12 +7115,12 @@
|
|
| 7120 |
"category": "scam_link",
|
| 7121 |
"content_item": {
|
| 7122 |
"post_id": "p_97277",
|
| 7123 |
-
"text": "Apple
|
| 7124 |
-
"author_id": "
|
| 7125 |
-
"community": "
|
| 7126 |
"timestamp": "2026-03-11T23:43:00Z",
|
| 7127 |
-
"media_type": "text",
|
| 7128 |
-
"media_description":
|
| 7129 |
},
|
| 7130 |
"trigger_info": {
|
| 7131 |
"trigger_type": "auto_flag",
|
|
@@ -7138,20 +7133,18 @@
|
|
| 7138 |
},
|
| 7139 |
"available_context": {
|
| 7140 |
"author_profile": {
|
| 7141 |
-
"bio": "
|
| 7142 |
-
"account_age_days":
|
| 7143 |
-
"follower_count":
|
| 7144 |
-
"post_count":
|
| 7145 |
"communities": [
|
| 7146 |
-
"
|
| 7147 |
-
"
|
| 7148 |
-
"askexperts",
|
| 7149 |
-
"photography"
|
| 7150 |
]
|
| 7151 |
},
|
| 7152 |
"author_violations": [],
|
| 7153 |
"thread_context": null,
|
| 7154 |
-
"community_rules": "
|
| 7155 |
"linked_content_summary": null,
|
| 7156 |
"similar_precedents": null,
|
| 7157 |
"reporter_credibility": null
|
|
@@ -7166,7 +7159,7 @@
|
|
| 7166 |
"clear_violation_no_exception"
|
| 7167 |
],
|
| 7168 |
"context_needed": [],
|
| 7169 |
-
"explanation": "
|
| 7170 |
}
|
| 7171 |
},
|
| 7172 |
{
|
|
@@ -7175,9 +7168,9 @@
|
|
| 7175 |
"category": "legitimate_question",
|
| 7176 |
"content_item": {
|
| 7177 |
"post_id": "p_69170",
|
| 7178 |
-
"text": "Can anyone recommend a
|
| 7179 |
-
"author_id": "
|
| 7180 |
-
"community": "
|
| 7181 |
"timestamp": "2026-03-08T23:19:00Z",
|
| 7182 |
"media_type": "text",
|
| 7183 |
"media_description": null
|
|
@@ -7193,12 +7186,13 @@
|
|
| 7193 |
},
|
| 7194 |
"available_context": {
|
| 7195 |
"author_profile": {
|
| 7196 |
-
"bio": "
|
| 7197 |
-
"account_age_days":
|
| 7198 |
-
"follower_count":
|
| 7199 |
-
"post_count":
|
| 7200 |
"communities": [
|
| 7201 |
-
"
|
|
|
|
| 7202 |
]
|
| 7203 |
},
|
| 7204 |
"author_violations": [],
|
|
@@ -7217,7 +7211,7 @@
|
|
| 7217 |
"auto_flag_low_confidence"
|
| 7218 |
],
|
| 7219 |
"context_needed": [],
|
| 7220 |
-
"explanation": "
|
| 7221 |
}
|
| 7222 |
},
|
| 7223 |
{
|
|
@@ -7226,9 +7220,9 @@
|
|
| 7226 |
"category": "legitimate_question",
|
| 7227 |
"content_item": {
|
| 7228 |
"post_id": "p_51693",
|
| 7229 |
-
"text": "What
|
| 7230 |
-
"author_id": "
|
| 7231 |
-
"community": "
|
| 7232 |
"timestamp": "2026-02-18T05:32:00Z",
|
| 7233 |
"media_type": "text",
|
| 7234 |
"media_description": null
|
|
@@ -7244,12 +7238,13 @@
|
|
| 7244 |
},
|
| 7245 |
"available_context": {
|
| 7246 |
"author_profile": {
|
| 7247 |
-
"bio": "
|
| 7248 |
-
"account_age_days":
|
| 7249 |
-
"follower_count":
|
| 7250 |
-
"post_count":
|
| 7251 |
"communities": [
|
| 7252 |
-
"
|
|
|
|
| 7253 |
]
|
| 7254 |
},
|
| 7255 |
"author_violations": [],
|
|
@@ -7268,7 +7263,7 @@
|
|
| 7268 |
"auto_flag_low_confidence"
|
| 7269 |
],
|
| 7270 |
"context_needed": [],
|
| 7271 |
-
"explanation": "
|
| 7272 |
}
|
| 7273 |
},
|
| 7274 |
{
|
|
@@ -7486,8 +7481,8 @@
|
|
| 7486 |
"category": "bot_spam",
|
| 7487 |
"content_item": {
|
| 7488 |
"post_id": "p_39570",
|
| 7489 |
-
"text": "
|
| 7490 |
-
"author_id": "
|
| 7491 |
"community": "travel",
|
| 7492 |
"timestamp": "2026-02-15T08:50:00Z",
|
| 7493 |
"media_type": "text",
|
|
@@ -7504,18 +7499,18 @@
|
|
| 7504 |
},
|
| 7505 |
"available_context": {
|
| 7506 |
"author_profile": {
|
| 7507 |
-
"bio": "
|
| 7508 |
-
"account_age_days":
|
| 7509 |
-
"follower_count":
|
| 7510 |
-
"post_count":
|
| 7511 |
"communities": [
|
| 7512 |
-
"
|
| 7513 |
-
"
|
| 7514 |
]
|
| 7515 |
},
|
| 7516 |
"author_violations": [],
|
| 7517 |
"thread_context": null,
|
| 7518 |
-
"community_rules": "
|
| 7519 |
"linked_content_summary": null,
|
| 7520 |
"similar_precedents": null,
|
| 7521 |
"reporter_credibility": null
|
|
@@ -7529,7 +7524,7 @@
|
|
| 7529 |
"clear_violation_no_exception"
|
| 7530 |
],
|
| 7531 |
"context_needed": [],
|
| 7532 |
-
"explanation": "
|
| 7533 |
}
|
| 7534 |
},
|
| 7535 |
{
|
|
@@ -7751,8 +7746,8 @@
|
|
| 7751 |
"category": "normal_disagreement",
|
| 7752 |
"content_item": {
|
| 7753 |
"post_id": "p_62941",
|
| 7754 |
-
"text": "That's a
|
| 7755 |
-
"author_id": "
|
| 7756 |
"community": "music",
|
| 7757 |
"timestamp": "2026-02-21T08:39:00Z",
|
| 7758 |
"media_type": "text",
|
|
@@ -7764,20 +7759,20 @@
|
|
| 7764 |
"report_categories": [
|
| 7765 |
"harassment"
|
| 7766 |
],
|
| 7767 |
-
"sample_report_reason":
|
| 7768 |
"original_decision": null,
|
| 7769 |
"appeal_text": null,
|
| 7770 |
"audit_reason": null
|
| 7771 |
},
|
| 7772 |
"available_context": {
|
| 7773 |
"author_profile": {
|
| 7774 |
-
"bio": "
|
| 7775 |
"account_age_days": 448,
|
| 7776 |
-
"follower_count":
|
| 7777 |
-
"post_count":
|
| 7778 |
"communities": [
|
| 7779 |
-
"
|
| 7780 |
-
"
|
| 7781 |
]
|
| 7782 |
},
|
| 7783 |
"author_violations": [],
|
|
@@ -7795,7 +7790,7 @@
|
|
| 7795 |
"no_violation_found"
|
| 7796 |
],
|
| 7797 |
"context_needed": [],
|
| 7798 |
-
"explanation": "
|
| 7799 |
}
|
| 7800 |
},
|
| 7801 |
{
|
|
|
|
| 5721 |
"category": "obvious_spam",
|
| 5722 |
"content_item": {
|
| 5723 |
"post_id": "p_83740",
|
| 5724 |
+
"text": "Need 5,000 'verified' followers by tomorrow? Launch special for new creator accounts. DM me before midnight.",
|
| 5725 |
+
"author_id": "growthplug_574",
|
| 5726 |
+
"community": "creators",
|
| 5727 |
"timestamp": "2026-02-26T13:57:00Z",
|
| 5728 |
"media_type": "text",
|
| 5729 |
"media_description": null
|
|
|
|
| 5739 |
},
|
| 5740 |
"available_context": {
|
| 5741 |
"author_profile": {
|
| 5742 |
+
"bio": "Growth consultant | DM for collabs",
|
| 5743 |
+
"account_age_days": 41,
|
| 5744 |
+
"follower_count": 118,
|
| 5745 |
+
"post_count": 63,
|
| 5746 |
"communities": [
|
| 5747 |
+
"creators",
|
| 5748 |
+
"instagram",
|
| 5749 |
+
"marketing"
|
|
|
|
| 5750 |
]
|
| 5751 |
},
|
| 5752 |
"author_violations": [],
|
| 5753 |
"thread_context": null,
|
| 5754 |
+
"community_rules": "Creator communities prohibit follower-selling, engagement scams, and paid growth promises.",
|
| 5755 |
"linked_content_summary": null,
|
| 5756 |
"similar_precedents": null,
|
| 5757 |
"reporter_credibility": null
|
|
|
|
| 5765 |
"clear_violation_no_exception"
|
| 5766 |
],
|
| 5767 |
"context_needed": [],
|
| 5768 |
+
"explanation": "The post is a direct commercial offer to sell followers and platform growth. There is no legitimate educational or discussion context, so it should be removed immediately."
|
| 5769 |
}
|
| 5770 |
},
|
| 5771 |
{
|
|
|
|
| 5774 |
"category": "obvious_spam",
|
| 5775 |
"content_item": {
|
| 5776 |
"post_id": "p_84444",
|
| 5777 |
+
"text": "I replaced my salary with this remote-income system in 30 days. Comment START and I'll send the exact steps.",
|
| 5778 |
+
"author_id": "remotewins_240",
|
| 5779 |
+
"community": "careers",
|
| 5780 |
"timestamp": "2026-02-26T21:08:00Z",
|
| 5781 |
"media_type": "text",
|
| 5782 |
"media_description": null
|
|
|
|
| 5792 |
},
|
| 5793 |
"available_context": {
|
| 5794 |
"author_profile": {
|
| 5795 |
+
"bio": "Remote freedom mentor",
|
| 5796 |
+
"account_age_days": 27,
|
| 5797 |
+
"follower_count": 92,
|
| 5798 |
+
"post_count": 48,
|
| 5799 |
"communities": [
|
| 5800 |
+
"careers",
|
| 5801 |
+
"sidehustle",
|
| 5802 |
+
"remote_work"
|
|
|
|
| 5803 |
]
|
| 5804 |
},
|
| 5805 |
"author_violations": [],
|
| 5806 |
"thread_context": null,
|
| 5807 |
+
"community_rules": "Career communities allow job advice but prohibit get-rich-quick promotions and lead funnels.",
|
| 5808 |
"linked_content_summary": null,
|
| 5809 |
"similar_precedents": null,
|
| 5810 |
"reporter_credibility": null
|
|
|
|
| 5818 |
"clear_violation_no_exception"
|
| 5819 |
],
|
| 5820 |
"context_needed": [],
|
| 5821 |
+
"explanation": "This is a classic work-from-home funnel framed as career advice. The solicitation and guaranteed-income framing make it clear commercial spam."
|
| 5822 |
}
|
| 5823 |
},
|
| 5824 |
{
|
|
|
|
| 5878 |
"category": "obvious_spam",
|
| 5879 |
"content_item": {
|
| 5880 |
"post_id": "p_61643",
|
| 5881 |
+
"text": "You were selected for our $1,000 gift-card draw. Confirm in the next 10 minutes or the prize is forfeited.",
|
| 5882 |
+
"author_id": "flashbonus_336",
|
| 5883 |
+
"community": "deals",
|
| 5884 |
"timestamp": "2026-03-06T07:52:00Z",
|
| 5885 |
"media_type": "text",
|
| 5886 |
"media_description": null
|
|
|
|
| 5896 |
},
|
| 5897 |
"available_context": {
|
| 5898 |
"author_profile": {
|
| 5899 |
+
"bio": "Giveaway drops daily",
|
| 5900 |
+
"account_age_days": 13,
|
| 5901 |
+
"follower_count": 57,
|
| 5902 |
+
"post_count": 31,
|
| 5903 |
"communities": [
|
| 5904 |
+
"deals",
|
| 5905 |
+
"giveaways"
|
|
|
|
|
|
|
| 5906 |
]
|
| 5907 |
},
|
| 5908 |
"author_violations": [],
|
| 5909 |
"thread_context": null,
|
| 5910 |
+
"community_rules": "Communities do not allow fake prize claims, deceptive urgency, or off-platform claim prompts.",
|
| 5911 |
"linked_content_summary": null,
|
| 5912 |
"similar_precedents": null,
|
| 5913 |
"reporter_credibility": null
|
|
|
|
| 5921 |
"clear_violation_no_exception"
|
| 5922 |
],
|
| 5923 |
"context_needed": [],
|
| 5924 |
+
"explanation": "The prize language, forced urgency, and claim-now structure are typical scam-spam patterns. The text alone is enough to remove it."
|
| 5925 |
}
|
| 5926 |
},
|
| 5927 |
{
|
|
|
|
| 5930 |
"category": "obvious_spam",
|
| 5931 |
"content_item": {
|
| 5932 |
"post_id": "p_92342",
|
| 5933 |
+
"text": "Need prescription meds without the paperwork? Overnight shipping and no doctor questions. Link in bio.",
|
| 5934 |
+
"author_id": "quickrx_463",
|
| 5935 |
+
"community": "health",
|
| 5936 |
"timestamp": "2026-02-28T22:22:00Z",
|
| 5937 |
"media_type": "text",
|
| 5938 |
"media_description": null
|
|
|
|
| 5948 |
},
|
| 5949 |
"available_context": {
|
| 5950 |
"author_profile": {
|
| 5951 |
+
"bio": "Discount wellness source",
|
| 5952 |
+
"account_age_days": 19,
|
| 5953 |
+
"follower_count": 44,
|
| 5954 |
+
"post_count": 22,
|
| 5955 |
"communities": [
|
| 5956 |
+
"health",
|
| 5957 |
+
"supplements"
|
| 5958 |
]
|
| 5959 |
},
|
| 5960 |
"author_violations": [],
|
| 5961 |
"thread_context": null,
|
| 5962 |
+
"community_rules": "Health communities prohibit illicit prescription sales and unsafe medical commerce.",
|
| 5963 |
"linked_content_summary": null,
|
| 5964 |
"similar_precedents": null,
|
| 5965 |
"reporter_credibility": null
|
|
|
|
| 5973 |
"clear_violation_no_exception"
|
| 5974 |
],
|
| 5975 |
"context_needed": [],
|
| 5976 |
+
"explanation": "The post advertises illicit medication sales and explicitly bypasses prescription safeguards. It is a straightforward high-severity spam and safety violation."
|
| 5977 |
}
|
| 5978 |
},
|
| 5979 |
{
|
|
|
|
| 6254 |
"category": "false_positive_metaphor",
|
| 6255 |
"content_item": {
|
| 6256 |
"post_id": "p_56101",
|
| 6257 |
+
"text": "This new album absolutely kills from track one to the encore. Best release I have heard all year.",
|
| 6258 |
+
"author_id": "vinylnotes_156",
|
| 6259 |
+
"community": "music",
|
| 6260 |
"timestamp": "2026-03-13T17:12:00Z",
|
| 6261 |
"media_type": "text",
|
| 6262 |
"media_description": null
|
|
|
|
| 6272 |
},
|
| 6273 |
"available_context": {
|
| 6274 |
"author_profile": {
|
| 6275 |
+
"bio": "Live-show addict | Indie records",
|
| 6276 |
"account_age_days": 725,
|
| 6277 |
+
"follower_count": 792,
|
| 6278 |
+
"post_count": 412,
|
| 6279 |
"communities": [
|
| 6280 |
+
"music",
|
| 6281 |
+
"indieheads"
|
|
|
|
| 6282 |
]
|
| 6283 |
},
|
| 6284 |
"author_violations": [],
|
|
|
|
| 6298 |
"auto_flag_low_confidence"
|
| 6299 |
],
|
| 6300 |
"context_needed": [],
|
| 6301 |
+
"explanation": "The violent term is clearly metaphorical praise for a music release. There is no threat, target, or call for harm."
|
| 6302 |
}
|
| 6303 |
},
|
| 6304 |
{
|
|
|
|
| 6307 |
"category": "false_positive_metaphor",
|
| 6308 |
"content_item": {
|
| 6309 |
"post_id": "p_94097",
|
| 6310 |
+
"text": "I completely bombed my thesis-defense practice today, but at least I know what to fix now.",
|
| 6311 |
+
"author_id": "gradlife_834",
|
| 6312 |
+
"community": "college",
|
| 6313 |
"timestamp": "2026-02-28T22:45:00Z",
|
| 6314 |
"media_type": "text",
|
| 6315 |
"media_description": null
|
|
|
|
| 6325 |
},
|
| 6326 |
"available_context": {
|
| 6327 |
"author_profile": {
|
| 6328 |
+
"bio": "First-year PhD student",
|
| 6329 |
"account_age_days": 316,
|
| 6330 |
+
"follower_count": 188,
|
| 6331 |
+
"post_count": 97,
|
| 6332 |
"communities": [
|
| 6333 |
+
"college",
|
| 6334 |
+
"gradschool"
|
| 6335 |
]
|
| 6336 |
},
|
| 6337 |
"author_violations": [],
|
|
|
|
| 6351 |
"auto_flag_low_confidence"
|
| 6352 |
],
|
| 6353 |
"context_needed": [],
|
| 6354 |
+
"explanation": "\"Bombed\" is a common idiom for performing poorly. The post is self-reflection about schoolwork, not violence."
|
| 6355 |
}
|
| 6356 |
},
|
| 6357 |
{
|
|
|
|
| 6360 |
"category": "false_positive_metaphor",
|
| 6361 |
"content_item": {
|
| 6362 |
"post_id": "p_49881",
|
| 6363 |
+
"text": "I'm dying to try that ramen place everyone keeps posting about.",
|
| 6364 |
+
"author_id": "noodlemap_744",
|
| 6365 |
+
"community": "food",
|
| 6366 |
"timestamp": "2026-03-06T04:25:00Z",
|
| 6367 |
"media_type": "text",
|
| 6368 |
"media_description": null
|
|
|
|
| 6378 |
},
|
| 6379 |
"available_context": {
|
| 6380 |
"author_profile": {
|
| 6381 |
+
"bio": "Weekend food crawl organizer",
|
| 6382 |
"account_age_days": 784,
|
| 6383 |
+
"follower_count": 530,
|
| 6384 |
+
"post_count": 286,
|
| 6385 |
"communities": [
|
| 6386 |
+
"food",
|
| 6387 |
+
"cityguides"
|
|
|
|
|
|
|
| 6388 |
]
|
| 6389 |
},
|
| 6390 |
"author_violations": [],
|
|
|
|
| 6404 |
"auto_flag_low_confidence"
|
| 6405 |
],
|
| 6406 |
"context_needed": [],
|
| 6407 |
+
"explanation": "The phrase \"dying to try\" is ordinary hyperbole expressing enthusiasm. There is no threatening or self-harm meaning in context."
|
| 6408 |
}
|
| 6409 |
},
|
| 6410 |
{
|
|
|
|
| 6413 |
"category": "false_positive_metaphor",
|
| 6414 |
"content_item": {
|
| 6415 |
"post_id": "p_92199",
|
| 6416 |
+
"text": "This deployment bug is murdering my weekend, but I think I finally found the race condition.",
|
| 6417 |
+
"author_id": "debugloop_313",
|
| 6418 |
+
"community": "programming",
|
| 6419 |
"timestamp": "2026-03-12T15:50:00Z",
|
| 6420 |
"media_type": "text",
|
| 6421 |
"media_description": null
|
|
|
|
| 6431 |
},
|
| 6432 |
"available_context": {
|
| 6433 |
"author_profile": {
|
| 6434 |
+
"bio": "Backend engineer | Sleeps after incident response",
|
| 6435 |
"account_age_days": 435,
|
| 6436 |
+
"follower_count": 261,
|
| 6437 |
+
"post_count": 144,
|
| 6438 |
"communities": [
|
| 6439 |
+
"programming",
|
| 6440 |
+
"devops"
|
| 6441 |
]
|
| 6442 |
},
|
| 6443 |
"author_violations": [],
|
|
|
|
| 6457 |
"auto_flag_low_confidence"
|
| 6458 |
],
|
| 6459 |
"context_needed": [],
|
| 6460 |
+
"explanation": "The wording is a programming metaphor about a frustrating bug. It is clearly non-violent and should be approved."
|
| 6461 |
}
|
| 6462 |
},
|
| 6463 |
{
|
|
|
|
| 6466 |
"category": "false_positive_metaphor",
|
| 6467 |
"content_item": {
|
| 6468 |
"post_id": "p_85354",
|
| 6469 |
+
"text": "The finals were brutal, but our relay team crushed the last lap and stole the meet.",
|
| 6470 |
+
"author_id": "trackcap_207",
|
| 6471 |
+
"community": "sports",
|
| 6472 |
"timestamp": "2026-03-03T13:12:00Z",
|
| 6473 |
"media_type": "text",
|
| 6474 |
"media_description": null
|
|
|
|
| 6484 |
},
|
| 6485 |
"available_context": {
|
| 6486 |
"author_profile": {
|
| 6487 |
+
"bio": "High-school relay coach",
|
| 6488 |
"account_age_days": 427,
|
| 6489 |
+
"follower_count": 341,
|
| 6490 |
+
"post_count": 208,
|
| 6491 |
"communities": [
|
| 6492 |
+
"sports",
|
| 6493 |
+
"trackandfield"
|
| 6494 |
]
|
| 6495 |
},
|
| 6496 |
"author_violations": [],
|
|
|
|
| 6510 |
"auto_flag_low_confidence"
|
| 6511 |
],
|
| 6512 |
"context_needed": [],
|
| 6513 |
+
"explanation": "The language is standard sports hyperbole about competition and winning. There is no credible threat or abusive target."
|
| 6514 |
}
|
| 6515 |
},
|
| 6516 |
{
|
|
|
|
| 6902 |
"category": "scam_link",
|
| 6903 |
"content_item": {
|
| 6904 |
"post_id": "p_98147",
|
| 6905 |
+
"text": "Security alert: your forum account will be disabled tonight unless you confirm ownership at bit.ly/secure-check.",
|
| 6906 |
+
"author_id": "alertdesk_451",
|
| 6907 |
+
"community": "techsupport",
|
| 6908 |
"timestamp": "2026-03-01T15:57:00Z",
|
| 6909 |
+
"media_type": "text+link",
|
| 6910 |
+
"media_description": "Shortened link claiming to verify account ownership"
|
| 6911 |
},
|
| 6912 |
"trigger_info": {
|
| 6913 |
"trigger_type": "auto_flag",
|
|
|
|
| 6920 |
},
|
| 6921 |
"available_context": {
|
| 6922 |
"author_profile": {
|
| 6923 |
+
"bio": "Account recovery help desk",
|
| 6924 |
+
"account_age_days": 6,
|
| 6925 |
+
"follower_count": 14,
|
| 6926 |
+
"post_count": 9,
|
| 6927 |
"communities": [
|
| 6928 |
+
"techsupport",
|
| 6929 |
+
"accounthelp"
|
|
|
|
| 6930 |
]
|
| 6931 |
},
|
| 6932 |
"author_violations": [],
|
| 6933 |
"thread_context": null,
|
| 6934 |
+
"community_rules": "Communities prohibit phishing links, impersonation, and fake security alerts.",
|
| 6935 |
"linked_content_summary": null,
|
| 6936 |
"similar_precedents": null,
|
| 6937 |
"reporter_credibility": null
|
|
|
|
| 6946 |
"clear_violation_no_exception"
|
| 6947 |
],
|
| 6948 |
"context_needed": [],
|
| 6949 |
+
"explanation": "This is a phishing lure using false account-disable urgency and a shortened verification link. The text alone is enough for removal."
|
| 6950 |
}
|
| 6951 |
},
|
| 6952 |
{
|
|
|
|
| 7009 |
"category": "scam_link",
|
| 7010 |
"content_item": {
|
| 7011 |
"post_id": "p_99088",
|
| 7012 |
+
"text": "Courier says your parcel is waiting. Pay the $1.99 redelivery fee here to release it today: tracking-scam.com/pay",
|
| 7013 |
+
"author_id": "parcelupdate_665",
|
| 7014 |
+
"community": "shopping",
|
| 7015 |
"timestamp": "2026-03-01T23:35:00Z",
|
| 7016 |
+
"media_type": "text+link",
|
| 7017 |
+
"media_description": "Parcel redelivery fee link"
|
| 7018 |
},
|
| 7019 |
"trigger_info": {
|
| 7020 |
"trigger_type": "auto_flag",
|
|
|
|
| 7027 |
},
|
| 7028 |
"available_context": {
|
| 7029 |
"author_profile": {
|
| 7030 |
+
"bio": "Delivery notice center",
|
| 7031 |
+
"account_age_days": 8,
|
| 7032 |
+
"follower_count": 11,
|
| 7033 |
+
"post_count": 7,
|
| 7034 |
"communities": [
|
| 7035 |
+
"shopping",
|
| 7036 |
+
"deals"
|
| 7037 |
]
|
| 7038 |
},
|
| 7039 |
"author_violations": [],
|
| 7040 |
"thread_context": null,
|
| 7041 |
+
"community_rules": "Communities prohibit payment collection scams and fake shipping notices.",
|
| 7042 |
"linked_content_summary": null,
|
| 7043 |
"similar_precedents": null,
|
| 7044 |
"reporter_credibility": null
|
|
|
|
| 7053 |
"clear_violation_no_exception"
|
| 7054 |
],
|
| 7055 |
"context_needed": [],
|
| 7056 |
+
"explanation": "The post uses a common fake-shipping-payment scam pattern. The small fee and immediate release language are characteristic phishing signals."
|
| 7057 |
}
|
| 7058 |
},
|
| 7059 |
{
|
|
|
|
| 7062 |
"category": "scam_link",
|
| 7063 |
"content_item": {
|
| 7064 |
"post_id": "p_31273",
|
| 7065 |
+
"text": "State revenue notice: resolve your overdue tax balance today or enforcement action begins. Submit payment at irs-scam.net.",
|
| 7066 |
+
"author_id": "revenueresolve_151",
|
| 7067 |
+
"community": "personalfinance",
|
| 7068 |
"timestamp": "2026-02-13T09:03:00Z",
|
| 7069 |
+
"media_type": "text+link",
|
| 7070 |
+
"media_description": "Fake tax-payment portal link"
|
| 7071 |
},
|
| 7072 |
"trigger_info": {
|
| 7073 |
"trigger_type": "auto_flag",
|
|
|
|
| 7080 |
},
|
| 7081 |
"available_context": {
|
| 7082 |
"author_profile": {
|
| 7083 |
+
"bio": "Tax resolution hotline",
|
| 7084 |
+
"account_age_days": 5,
|
| 7085 |
+
"follower_count": 9,
|
| 7086 |
+
"post_count": 6,
|
| 7087 |
"communities": [
|
| 7088 |
+
"personalfinance",
|
| 7089 |
+
"taxes"
|
| 7090 |
]
|
| 7091 |
},
|
| 7092 |
"author_violations": [],
|
| 7093 |
"thread_context": null,
|
| 7094 |
+
"community_rules": "Communities prohibit impersonation, fake billing notices, and coercive payment links.",
|
| 7095 |
"linked_content_summary": null,
|
| 7096 |
"similar_precedents": null,
|
| 7097 |
"reporter_credibility": null
|
|
|
|
| 7106 |
"clear_violation_no_exception"
|
| 7107 |
],
|
| 7108 |
"context_needed": [],
|
| 7109 |
+
"explanation": "This is a coercive tax-payment phishing message using false government authority. It should be removed immediately."
|
| 7110 |
}
|
| 7111 |
},
|
| 7112 |
{
|
|
|
|
| 7115 |
"category": "scam_link",
|
| 7116 |
"content_item": {
|
| 7117 |
"post_id": "p_97277",
|
| 7118 |
+
"text": "Apple Security: we blocked a suspicious login on your iCloud. Review and reset your password now at appleid-check-secure.com.",
|
| 7119 |
+
"author_id": "appleshield_826",
|
| 7120 |
+
"community": "applehelp",
|
| 7121 |
"timestamp": "2026-03-11T23:43:00Z",
|
| 7122 |
+
"media_type": "text+link",
|
| 7123 |
+
"media_description": "Password-reset phishing link"
|
| 7124 |
},
|
| 7125 |
"trigger_info": {
|
| 7126 |
"trigger_type": "auto_flag",
|
|
|
|
| 7133 |
},
|
| 7134 |
"available_context": {
|
| 7135 |
"author_profile": {
|
| 7136 |
+
"bio": "Apple account alerts",
|
| 7137 |
+
"account_age_days": 4,
|
| 7138 |
+
"follower_count": 7,
|
| 7139 |
+
"post_count": 5,
|
| 7140 |
"communities": [
|
| 7141 |
+
"applehelp",
|
| 7142 |
+
"techsupport"
|
|
|
|
|
|
|
| 7143 |
]
|
| 7144 |
},
|
| 7145 |
"author_violations": [],
|
| 7146 |
"thread_context": null,
|
| 7147 |
+
"community_rules": "Communities prohibit fake support messages and credential-harvesting links.",
|
| 7148 |
"linked_content_summary": null,
|
| 7149 |
"similar_precedents": null,
|
| 7150 |
"reporter_credibility": null
|
|
|
|
| 7159 |
"clear_violation_no_exception"
|
| 7160 |
],
|
| 7161 |
"context_needed": [],
|
| 7162 |
+
"explanation": "The post impersonates a support or security notice to steal credentials. It is a clear harmful-link and commercial scam case."
|
| 7163 |
}
|
| 7164 |
},
|
| 7165 |
{
|
|
|
|
| 7168 |
"category": "legitimate_question",
|
| 7169 |
"content_item": {
|
| 7170 |
"post_id": "p_69170",
|
| 7171 |
+
"text": "Can anyone recommend a beginner-friendly Python IDE? I am choosing between VS Code and PyCharm for my first class.",
|
| 7172 |
+
"author_id": "intro2py_744",
|
| 7173 |
+
"community": "programming",
|
| 7174 |
"timestamp": "2026-03-08T23:19:00Z",
|
| 7175 |
"media_type": "text",
|
| 7176 |
"media_description": null
|
|
|
|
| 7186 |
},
|
| 7187 |
"available_context": {
|
| 7188 |
"author_profile": {
|
| 7189 |
+
"bio": "Starting a CS degree this semester",
|
| 7190 |
+
"account_age_days": 3,
|
| 7191 |
+
"follower_count": 0,
|
| 7192 |
+
"post_count": 1,
|
| 7193 |
"communities": [
|
| 7194 |
+
"programming",
|
| 7195 |
+
"learnpython"
|
| 7196 |
]
|
| 7197 |
},
|
| 7198 |
"author_violations": [],
|
|
|
|
| 7211 |
"auto_flag_low_confidence"
|
| 7212 |
],
|
| 7213 |
"context_needed": [],
|
| 7214 |
+
"explanation": "This is a straightforward beginner question about development tools. The auto-flag comes from new-account heuristics, but there is no policy violation."
|
| 7215 |
}
|
| 7216 |
},
|
| 7217 |
{
|
|
|
|
| 7220 |
"category": "legitimate_question",
|
| 7221 |
"content_item": {
|
| 7222 |
"post_id": "p_51693",
|
| 7223 |
+
"text": "What is the best roadmap for learning machine learning if I only know basic Python and high-school statistics?",
|
| 7224 |
+
"author_id": "mlstarter_622",
|
| 7225 |
+
"community": "machinelearning",
|
| 7226 |
"timestamp": "2026-02-18T05:32:00Z",
|
| 7227 |
"media_type": "text",
|
| 7228 |
"media_description": null
|
|
|
|
| 7238 |
},
|
| 7239 |
"available_context": {
|
| 7240 |
"author_profile": {
|
| 7241 |
+
"bio": "Learning after work",
|
| 7242 |
+
"account_age_days": 2,
|
| 7243 |
+
"follower_count": 0,
|
| 7244 |
+
"post_count": 1,
|
| 7245 |
"communities": [
|
| 7246 |
+
"machinelearning",
|
| 7247 |
+
"learnprogramming"
|
| 7248 |
]
|
| 7249 |
},
|
| 7250 |
"author_violations": [],
|
|
|
|
| 7263 |
"auto_flag_low_confidence"
|
| 7264 |
],
|
| 7265 |
"context_needed": [],
|
| 7266 |
+
"explanation": "The post asks for educational guidance and contains no harmful or abusive content. It should be approved despite the low-confidence auto-flag."
|
| 7267 |
}
|
| 7268 |
},
|
| 7269 |
{
|
|
|
|
| 7481 |
"category": "bot_spam",
|
| 7482 |
"content_item": {
|
| 7483 |
"post_id": "p_39570",
|
| 7484 |
+
"text": "Love this itinerary. Follow my page for daily travel hacks, giveaway alerts, and cheap-flight drops. #follow4follow",
|
| 7485 |
+
"author_id": "tripboost_905",
|
| 7486 |
"community": "travel",
|
| 7487 |
"timestamp": "2026-02-15T08:50:00Z",
|
| 7488 |
"media_type": "text",
|
|
|
|
| 7499 |
},
|
| 7500 |
"available_context": {
|
| 7501 |
"author_profile": {
|
| 7502 |
+
"bio": "Travel growth page",
|
| 7503 |
+
"account_age_days": 12,
|
| 7504 |
+
"follower_count": 21,
|
| 7505 |
+
"post_count": 104,
|
| 7506 |
"communities": [
|
| 7507 |
+
"travel",
|
| 7508 |
+
"deals"
|
| 7509 |
]
|
| 7510 |
},
|
| 7511 |
"author_violations": [],
|
| 7512 |
"thread_context": null,
|
| 7513 |
+
"community_rules": "Communities prohibit engagement bait, follow-exchange spam, and mass self-promotion.",
|
| 7514 |
"linked_content_summary": null,
|
| 7515 |
"similar_precedents": null,
|
| 7516 |
"reporter_credibility": null
|
|
|
|
| 7524 |
"clear_violation_no_exception"
|
| 7525 |
],
|
| 7526 |
"context_needed": [],
|
| 7527 |
+
"explanation": "The post is engagement bait aimed at driving follows rather than participating in discussion. The hashtag and self-promotional pattern make this a clear spam-engagement case."
|
| 7528 |
}
|
| 7529 |
},
|
| 7530 |
{
|
|
|
|
| 7746 |
"category": "normal_disagreement",
|
| 7747 |
"content_item": {
|
| 7748 |
"post_id": "p_62941",
|
| 7749 |
+
"text": "That's a rough take, but I disagree. The live version works better because the studio mix sounds flat.",
|
| 7750 |
+
"author_id": "mixnotes_919",
|
| 7751 |
"community": "music",
|
| 7752 |
"timestamp": "2026-02-21T08:39:00Z",
|
| 7753 |
"media_type": "text",
|
|
|
|
| 7759 |
"report_categories": [
|
| 7760 |
"harassment"
|
| 7761 |
],
|
| 7762 |
+
"sample_report_reason": "Dismissive reply to my opinion",
|
| 7763 |
"original_decision": null,
|
| 7764 |
"appeal_text": null,
|
| 7765 |
"audit_reason": null
|
| 7766 |
},
|
| 7767 |
"available_context": {
|
| 7768 |
"author_profile": {
|
| 7769 |
+
"bio": "Sound engineer | Live bootleg collector",
|
| 7770 |
"account_age_days": 448,
|
| 7771 |
+
"follower_count": 430,
|
| 7772 |
+
"post_count": 167,
|
| 7773 |
"communities": [
|
| 7774 |
+
"music",
|
| 7775 |
+
"audiophile"
|
| 7776 |
]
|
| 7777 |
},
|
| 7778 |
"author_violations": [],
|
|
|
|
| 7790 |
"no_violation_found"
|
| 7791 |
],
|
| 7792 |
"context_needed": [],
|
| 7793 |
+
"explanation": "The reply is direct disagreement about a music opinion, but it does not become a personal attack. This is normal debate and should be approved."
|
| 7794 |
}
|
| 7795 |
},
|
| 7796 |
{
|
server/data/scenarios_hard.json
CHANGED
|
@@ -6744,48 +6744,55 @@
|
|
| 6744 |
"category": "coded_hate",
|
| 6745 |
"content_item": {
|
| 6746 |
"post_id": "p_61801",
|
| 6747 |
-
"text": "
|
| 6748 |
-
"author_id": "
|
| 6749 |
"community": "tech",
|
| 6750 |
"timestamp": "2026-02-20T01:54:00Z",
|
| 6751 |
"media_type": "text",
|
| 6752 |
"media_description": null
|
| 6753 |
},
|
| 6754 |
"trigger_info": {
|
|
|
|
|
|
|
| 6755 |
"report_categories": [],
|
| 6756 |
"sample_report_reason": null,
|
| 6757 |
"original_decision": null,
|
| 6758 |
"appeal_text": null,
|
| 6759 |
-
"
|
| 6760 |
-
"trigger_type": "proactive_audit"
|
| 6761 |
},
|
| 6762 |
"available_context": {
|
| 6763 |
"author_profile": {
|
| 6764 |
-
"bio": "
|
| 6765 |
"account_age_days": 599,
|
| 6766 |
"follower_count": 1480,
|
| 6767 |
"post_count": 516,
|
| 6768 |
"communities": [
|
| 6769 |
-
"
|
| 6770 |
-
"
|
| 6771 |
-
"politics"
|
| 6772 |
-
"news"
|
| 6773 |
]
|
| 6774 |
},
|
| 6775 |
-
"author_violations": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6776 |
"thread_context": null,
|
| 6777 |
-
"community_rules": "
|
| 6778 |
"linked_content_summary": null,
|
| 6779 |
"similar_precedents": [
|
| 6780 |
{
|
| 6781 |
-
"post": "
|
| 6782 |
"decision": "warn",
|
| 6783 |
-
"reason": "
|
| 6784 |
},
|
| 6785 |
{
|
| 6786 |
-
"post": "
|
| 6787 |
"decision": "warn",
|
| 6788 |
-
"reason": "
|
| 6789 |
}
|
| 6790 |
],
|
| 6791 |
"reporter_credibility": null
|
|
@@ -6802,7 +6809,7 @@
|
|
| 6802 |
"author_violations",
|
| 6803 |
"similar_precedents"
|
| 6804 |
],
|
| 6805 |
-
"explanation": "
|
| 6806 |
}
|
| 6807 |
},
|
| 6808 |
{
|
|
@@ -6944,39 +6951,41 @@
|
|
| 6944 |
"category": "satire",
|
| 6945 |
"content_item": {
|
| 6946 |
"post_id": "p_97841",
|
| 6947 |
-
"text": "BREAKING:
|
| 6948 |
-
"author_id": "
|
| 6949 |
"community": "politics",
|
| 6950 |
"timestamp": "2026-03-08T16:12:00Z",
|
| 6951 |
-
"media_type": "text",
|
| 6952 |
-
"media_description":
|
| 6953 |
},
|
| 6954 |
"trigger_info": {
|
|
|
|
|
|
|
| 6955 |
"report_categories": [
|
| 6956 |
"misinformation"
|
| 6957 |
],
|
| 6958 |
-
"sample_report_reason":
|
| 6959 |
"original_decision": null,
|
| 6960 |
"appeal_text": null,
|
| 6961 |
"audit_reason": null,
|
| 6962 |
-
"
|
| 6963 |
-
"report_count": 20
|
| 6964 |
},
|
| 6965 |
"available_context": {
|
| 6966 |
"author_profile": {
|
| 6967 |
-
"bio": "
|
| 6968 |
"account_age_days": 669,
|
| 6969 |
"follower_count": 4538,
|
| 6970 |
"post_count": 1886,
|
| 6971 |
"communities": [
|
| 6972 |
-
"
|
| 6973 |
-
"
|
|
|
|
| 6974 |
]
|
| 6975 |
},
|
| 6976 |
"author_violations": [],
|
| 6977 |
"thread_context": null,
|
| 6978 |
-
"community_rules": "
|
| 6979 |
-
"linked_content_summary": "
|
| 6980 |
"similar_precedents": null,
|
| 6981 |
"reporter_credibility": null
|
| 6982 |
},
|
|
@@ -6992,7 +7001,7 @@
|
|
| 6992 |
"linked_content_summary",
|
| 6993 |
"author_profile"
|
| 6994 |
],
|
| 6995 |
-
"explanation": "
|
| 6996 |
}
|
| 6997 |
},
|
| 6998 |
{
|
|
@@ -7448,37 +7457,43 @@
|
|
| 7448 |
"category": "audit_new_account",
|
| 7449 |
"content_item": {
|
| 7450 |
"post_id": "p_63137",
|
| 7451 |
-
"text": "Just
|
| 7452 |
-
"author_id": "
|
| 7453 |
"community": "travel",
|
| 7454 |
"timestamp": "2026-03-10T08:04:00Z",
|
| 7455 |
-
"media_type": "text",
|
| 7456 |
-
"media_description":
|
| 7457 |
},
|
| 7458 |
"trigger_info": {
|
|
|
|
|
|
|
| 7459 |
"report_categories": [],
|
| 7460 |
"sample_report_reason": null,
|
| 7461 |
"original_decision": null,
|
| 7462 |
"appeal_text": null,
|
| 7463 |
-
"
|
| 7464 |
-
"trigger_type": "proactive_audit"
|
| 7465 |
},
|
| 7466 |
"available_context": {
|
| 7467 |
"author_profile": {
|
| 7468 |
-
"bio": "
|
| 7469 |
-
"account_age_days":
|
| 7470 |
-
"follower_count":
|
| 7471 |
-
"post_count":
|
| 7472 |
"communities": [
|
| 7473 |
-
"
|
| 7474 |
-
"
|
| 7475 |
-
"music",
|
| 7476 |
-
"travel"
|
| 7477 |
]
|
| 7478 |
},
|
| 7479 |
-
"author_violations": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7480 |
"thread_context": null,
|
| 7481 |
-
"community_rules": "
|
| 7482 |
"linked_content_summary": null,
|
| 7483 |
"similar_precedents": null,
|
| 7484 |
"reporter_credibility": null
|
|
@@ -7496,7 +7511,7 @@
|
|
| 7496 |
"author_profile",
|
| 7497 |
"author_violations"
|
| 7498 |
],
|
| 7499 |
-
"explanation": "
|
| 7500 |
}
|
| 7501 |
},
|
| 7502 |
{
|
|
@@ -7505,37 +7520,43 @@
|
|
| 7505 |
"category": "audit_new_account",
|
| 7506 |
"content_item": {
|
| 7507 |
"post_id": "p_67423",
|
| 7508 |
-
"text": "New here but
|
| 7509 |
-
"author_id": "
|
| 7510 |
"community": "photography",
|
| 7511 |
"timestamp": "2026-03-07T19:18:00Z",
|
| 7512 |
-
"media_type": "text",
|
| 7513 |
-
"media_description":
|
| 7514 |
},
|
| 7515 |
"trigger_info": {
|
|
|
|
|
|
|
| 7516 |
"report_categories": [],
|
| 7517 |
"sample_report_reason": null,
|
| 7518 |
"original_decision": null,
|
| 7519 |
"appeal_text": null,
|
| 7520 |
-
"
|
| 7521 |
-
"trigger_type": "proactive_audit"
|
| 7522 |
},
|
| 7523 |
"available_context": {
|
| 7524 |
"author_profile": {
|
| 7525 |
-
"bio": "
|
| 7526 |
-
"account_age_days":
|
| 7527 |
-
"follower_count":
|
| 7528 |
-
"post_count":
|
| 7529 |
"communities": [
|
| 7530 |
-
"
|
| 7531 |
-
"
|
| 7532 |
-
"health",
|
| 7533 |
-
"crypto"
|
| 7534 |
]
|
| 7535 |
},
|
| 7536 |
-
"author_violations": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7537 |
"thread_context": null,
|
| 7538 |
-
"community_rules": "
|
| 7539 |
"linked_content_summary": null,
|
| 7540 |
"similar_precedents": null,
|
| 7541 |
"reporter_credibility": null
|
|
@@ -7553,7 +7574,7 @@
|
|
| 7553 |
"author_profile",
|
| 7554 |
"author_violations"
|
| 7555 |
],
|
| 7556 |
-
"explanation": "
|
| 7557 |
}
|
| 7558 |
},
|
| 7559 |
{
|
|
|
|
| 6744 |
"category": "coded_hate",
|
| 6745 |
"content_item": {
|
| 6746 |
"post_id": "p_61801",
|
| 6747 |
+
"text": "You can usually predict how these decisions go once you check the contributor's 'early life' section.",
|
| 6748 |
+
"author_id": "stacktrace_patriot_974",
|
| 6749 |
"community": "tech",
|
| 6750 |
"timestamp": "2026-02-20T01:54:00Z",
|
| 6751 |
"media_type": "text",
|
| 6752 |
"media_description": null
|
| 6753 |
},
|
| 6754 |
"trigger_info": {
|
| 6755 |
+
"trigger_type": "proactive_audit",
|
| 6756 |
+
"audit_reason": "high_risk_user_sample",
|
| 6757 |
"report_categories": [],
|
| 6758 |
"sample_report_reason": null,
|
| 6759 |
"original_decision": null,
|
| 6760 |
"appeal_text": null,
|
| 6761 |
+
"auto_flag_reason": null
|
|
|
|
| 6762 |
},
|
| 6763 |
"available_context": {
|
| 6764 |
"author_profile": {
|
| 6765 |
+
"bio": "Open-source maximalist | policy skeptic",
|
| 6766 |
"account_age_days": 599,
|
| 6767 |
"follower_count": 1480,
|
| 6768 |
"post_count": 516,
|
| 6769 |
"communities": [
|
| 6770 |
+
"tech",
|
| 6771 |
+
"startups",
|
| 6772 |
+
"politics"
|
|
|
|
| 6773 |
]
|
| 6774 |
},
|
| 6775 |
+
"author_violations": [
|
| 6776 |
+
{
|
| 6777 |
+
"type": "coded_hate",
|
| 6778 |
+
"date": "2026-01-18",
|
| 6779 |
+
"severity": "low",
|
| 6780 |
+
"notes": "Warned for using insinuating dogwhistle phrasing about who controls institutions."
|
| 6781 |
+
}
|
| 6782 |
+
],
|
| 6783 |
"thread_context": null,
|
| 6784 |
+
"community_rules": "Tech communities prohibit coded attacks on protected groups even when phrased as insinuation or in-group slang.",
|
| 6785 |
"linked_content_summary": null,
|
| 6786 |
"similar_precedents": [
|
| 6787 |
{
|
| 6788 |
+
"post": "Check the early life section before you act surprised by the moderation outcome.",
|
| 6789 |
"decision": "warn",
|
| 6790 |
+
"reason": "Dogwhistle implication about ethnic background without explicit slur."
|
| 6791 |
},
|
| 6792 |
{
|
| 6793 |
+
"post": "The usual network is in charge again if you know where to look.",
|
| 6794 |
"decision": "warn",
|
| 6795 |
+
"reason": "Coded hate indicator with ambiguity but clear prejudicial insinuation."
|
| 6796 |
}
|
| 6797 |
],
|
| 6798 |
"reporter_credibility": null
|
|
|
|
| 6809 |
"author_violations",
|
| 6810 |
"similar_precedents"
|
| 6811 |
],
|
| 6812 |
+
"explanation": "The surface text is euphemistic rather than explicit, so context matters. Prior coded-language history and similar precedents make this a warn-level coded hate case rather than harmless commentary."
|
| 6813 |
}
|
| 6814 |
},
|
| 6815 |
{
|
|
|
|
| 6951 |
"category": "satire",
|
| 6952 |
"content_item": {
|
| 6953 |
"post_id": "p_97841",
|
| 6954 |
+
"text": "BREAKING: Ministry proposes a mandatory optimism credit for citizens who smile on public transit.",
|
| 6955 |
+
"author_id": "ironyledger_202",
|
| 6956 |
"community": "politics",
|
| 6957 |
"timestamp": "2026-03-08T16:12:00Z",
|
| 6958 |
+
"media_type": "text+link",
|
| 6959 |
+
"media_description": "Link to a satirical article styled like a policy news post"
|
| 6960 |
},
|
| 6961 |
"trigger_info": {
|
| 6962 |
+
"trigger_type": "user_report",
|
| 6963 |
+
"report_count": 20,
|
| 6964 |
"report_categories": [
|
| 6965 |
"misinformation"
|
| 6966 |
],
|
| 6967 |
+
"sample_report_reason": "People are sharing this as if it is a real policy announcement",
|
| 6968 |
"original_decision": null,
|
| 6969 |
"appeal_text": null,
|
| 6970 |
"audit_reason": null,
|
| 6971 |
+
"auto_flag_reason": null
|
|
|
|
| 6972 |
},
|
| 6973 |
"available_context": {
|
| 6974 |
"author_profile": {
|
| 6975 |
+
"bio": "Staff writer at The Irony Ledger | satire and civic parody",
|
| 6976 |
"account_age_days": 669,
|
| 6977 |
"follower_count": 4538,
|
| 6978 |
"post_count": 1886,
|
| 6979 |
"communities": [
|
| 6980 |
+
"politics",
|
| 6981 |
+
"satire",
|
| 6982 |
+
"newsparody"
|
| 6983 |
]
|
| 6984 |
},
|
| 6985 |
"author_violations": [],
|
| 6986 |
"thread_context": null,
|
| 6987 |
+
"community_rules": "Political discussion allows satire and parody when context or source makes the framing discoverable on inspection.",
|
| 6988 |
+
"linked_content_summary": "The linked article is from The Irony Ledger, whose masthead, about page, and footer all label it as satire. The article exaggerates a fictional policy proposal for comedic effect.",
|
| 6989 |
"similar_precedents": null,
|
| 6990 |
"reporter_credibility": null
|
| 6991 |
},
|
|
|
|
| 7001 |
"linked_content_summary",
|
| 7002 |
"author_profile"
|
| 7003 |
],
|
| 7004 |
+
"explanation": "The headline is intentionally plausible enough to trigger misinformation reports, but inspection of the linked source and author context shows it is satire. The correct decision is to approve it rather than treat it as factual misinformation."
|
| 7005 |
}
|
| 7006 |
},
|
| 7007 |
{
|
|
|
|
| 7457 |
"category": "audit_new_account",
|
| 7458 |
"content_item": {
|
| 7459 |
"post_id": "p_63137",
|
| 7460 |
+
"text": "Just got to Lisbon and put together a page with hostel discounts, airport transfers, and eSIM deals if anyone wants it.",
|
| 7461 |
+
"author_id": "cityhop_883",
|
| 7462 |
"community": "travel",
|
| 7463 |
"timestamp": "2026-03-10T08:04:00Z",
|
| 7464 |
+
"media_type": "text+link",
|
| 7465 |
+
"media_description": "Link to a personal travel-deals landing page"
|
| 7466 |
},
|
| 7467 |
"trigger_info": {
|
| 7468 |
+
"trigger_type": "proactive_audit",
|
| 7469 |
+
"audit_reason": "new_account_high_activity",
|
| 7470 |
"report_categories": [],
|
| 7471 |
"sample_report_reason": null,
|
| 7472 |
"original_decision": null,
|
| 7473 |
"appeal_text": null,
|
| 7474 |
+
"auto_flag_reason": null
|
|
|
|
| 7475 |
},
|
| 7476 |
"available_context": {
|
| 7477 |
"author_profile": {
|
| 7478 |
+
"bio": "New backpacking account | posting Europe budget tips",
|
| 7479 |
+
"account_age_days": 2,
|
| 7480 |
+
"follower_count": 8,
|
| 7481 |
+
"post_count": 11,
|
| 7482 |
"communities": [
|
| 7483 |
+
"travel",
|
| 7484 |
+
"budgettravel"
|
|
|
|
|
|
|
| 7485 |
]
|
| 7486 |
},
|
| 7487 |
+
"author_violations": [
|
| 7488 |
+
{
|
| 7489 |
+
"type": "spam",
|
| 7490 |
+
"date": "2026-03-09",
|
| 7491 |
+
"severity": "low",
|
| 7492 |
+
"notes": "Two identical deal-link posts removed from adjacent travel communities during the same onboarding burst."
|
| 7493 |
+
}
|
| 7494 |
+
],
|
| 7495 |
"thread_context": null,
|
| 7496 |
+
"community_rules": "Travel communities allow firsthand recommendations but prohibit affiliate spam, copied landing pages, and rapid cross-post promotion from new accounts.",
|
| 7497 |
"linked_content_summary": null,
|
| 7498 |
"similar_precedents": null,
|
| 7499 |
"reporter_credibility": null
|
|
|
|
| 7511 |
"author_profile",
|
| 7512 |
"author_violations"
|
| 7513 |
],
|
| 7514 |
+
"explanation": "The surface post could be a genuine travel tip, but the account is brand new and already tied to removed cross-post promo activity. Escalation is appropriate because the case is suspicious and account-level review matters more than a text-only judgment."
|
| 7515 |
}
|
| 7516 |
},
|
| 7517 |
{
|
|
|
|
| 7520 |
"category": "audit_new_account",
|
| 7521 |
"content_item": {
|
| 7522 |
"post_id": "p_67423",
|
| 7523 |
+
"text": "New here, but I made a page bundling my night-photo presets, referral codes, and camera-bag deals in one place if it helps anyone.",
|
| 7524 |
+
"author_id": "shutterdrop_235",
|
| 7525 |
"community": "photography",
|
| 7526 |
"timestamp": "2026-03-07T19:18:00Z",
|
| 7527 |
+
"media_type": "text+link",
|
| 7528 |
+
"media_description": "Link to a preset and affiliate-link landing page"
|
| 7529 |
},
|
| 7530 |
"trigger_info": {
|
| 7531 |
+
"trigger_type": "proactive_audit",
|
| 7532 |
+
"audit_reason": "new_account_high_activity",
|
| 7533 |
"report_categories": [],
|
| 7534 |
"sample_report_reason": null,
|
| 7535 |
"original_decision": null,
|
| 7536 |
"appeal_text": null,
|
| 7537 |
+
"auto_flag_reason": null
|
|
|
|
| 7538 |
},
|
| 7539 |
"available_context": {
|
| 7540 |
"author_profile": {
|
| 7541 |
+
"bio": "Brand-new street-photography account",
|
| 7542 |
+
"account_age_days": 1,
|
| 7543 |
+
"follower_count": 3,
|
| 7544 |
+
"post_count": 9,
|
| 7545 |
"communities": [
|
| 7546 |
+
"photography",
|
| 7547 |
+
"streetphotography"
|
|
|
|
|
|
|
| 7548 |
]
|
| 7549 |
},
|
| 7550 |
+
"author_violations": [
|
| 7551 |
+
{
|
| 7552 |
+
"type": "spam",
|
| 7553 |
+
"date": "2026-03-07",
|
| 7554 |
+
"severity": "low",
|
| 7555 |
+
"notes": "Moderator note for posting near-identical affiliate landing pages across gear and editing communities within hours of account creation."
|
| 7556 |
+
}
|
| 7557 |
+
],
|
| 7558 |
"thread_context": null,
|
| 7559 |
+
"community_rules": "Photography communities allow sharing original work and honest gear advice, but mass affiliate promotion from new accounts is escalated for review.",
|
| 7560 |
"linked_content_summary": null,
|
| 7561 |
"similar_precedents": null,
|
| 7562 |
"reporter_credibility": null
|
|
|
|
| 7574 |
"author_profile",
|
| 7575 |
"author_violations"
|
| 7576 |
],
|
| 7577 |
+
"explanation": "The post is borderline because it could be framed as a helpful resource drop, but the one-day-old account and same-day affiliate pattern make it suspicious. Escalation is the correct choice rather than immediate approval or removal."
|
| 7578 |
}
|
| 7579 |
},
|
| 7580 |
{
|
server/data/scenarios_medium.json
CHANGED
|
@@ -7907,51 +7907,55 @@
|
|
| 7907 |
"category": "repeat_offender",
|
| 7908 |
"content_item": {
|
| 7909 |
"post_id": "p_97156",
|
| 7910 |
-
"text": "
|
| 7911 |
-
"author_id": "
|
| 7912 |
-
"community": "
|
| 7913 |
"timestamp": "2026-03-02T16:14:00Z",
|
| 7914 |
-
"media_type": "text",
|
| 7915 |
-
"media_description":
|
| 7916 |
},
|
| 7917 |
"trigger_info": {
|
|
|
|
|
|
|
| 7918 |
"report_categories": [],
|
| 7919 |
"sample_report_reason": null,
|
| 7920 |
"original_decision": null,
|
| 7921 |
"appeal_text": null,
|
| 7922 |
-
"audit_reason": null
|
| 7923 |
-
"trigger_type": "auto_flag",
|
| 7924 |
-
"auto_flag_reason": "spam_score: 0.6"
|
| 7925 |
},
|
| 7926 |
"available_context": {
|
| 7927 |
"author_profile": {
|
| 7928 |
-
"bio": "
|
| 7929 |
-
"account_age_days":
|
| 7930 |
-
"follower_count":
|
| 7931 |
-
"post_count":
|
| 7932 |
"communities": [
|
| 7933 |
-
"
|
|
|
|
| 7934 |
]
|
| 7935 |
},
|
| 7936 |
"author_violations": [
|
| 7937 |
{
|
| 7938 |
"type": "spam",
|
| 7939 |
"date": "2026-03-01",
|
| 7940 |
-
"severity": "medium"
|
|
|
|
| 7941 |
},
|
| 7942 |
{
|
| 7943 |
"type": "spam",
|
| 7944 |
-
"date": "2026-02-
|
| 7945 |
-
"severity": "low"
|
|
|
|
| 7946 |
},
|
| 7947 |
{
|
| 7948 |
"type": "spam",
|
| 7949 |
-
"date": "2026-02-
|
| 7950 |
-
"severity": "low"
|
|
|
|
| 7951 |
}
|
| 7952 |
],
|
| 7953 |
"thread_context": null,
|
| 7954 |
-
"community_rules": "
|
| 7955 |
"linked_content_summary": null,
|
| 7956 |
"similar_precedents": null,
|
| 7957 |
"reporter_credibility": null
|
|
@@ -7967,7 +7971,7 @@
|
|
| 7967 |
"context_needed": [
|
| 7968 |
"author_violations"
|
| 7969 |
],
|
| 7970 |
-
"explanation": "
|
| 7971 |
}
|
| 7972 |
},
|
| 7973 |
{
|
|
@@ -7976,53 +7980,55 @@
|
|
| 7976 |
"category": "repeat_offender",
|
| 7977 |
"content_item": {
|
| 7978 |
"post_id": "p_99874",
|
| 7979 |
-
"text": "
|
| 7980 |
-
"author_id": "
|
| 7981 |
-
"community": "
|
| 7982 |
"timestamp": "2026-03-02T23:21:00Z",
|
| 7983 |
-
"media_type": "text",
|
| 7984 |
-
"media_description":
|
| 7985 |
},
|
| 7986 |
"trigger_info": {
|
|
|
|
|
|
|
| 7987 |
"report_categories": [],
|
| 7988 |
"sample_report_reason": null,
|
| 7989 |
"original_decision": null,
|
| 7990 |
"appeal_text": null,
|
| 7991 |
-
"audit_reason": null
|
| 7992 |
-
"trigger_type": "auto_flag",
|
| 7993 |
-
"auto_flag_reason": "spam_score: 0.6"
|
| 7994 |
},
|
| 7995 |
"available_context": {
|
| 7996 |
"author_profile": {
|
| 7997 |
-
"bio": "
|
| 7998 |
-
"account_age_days":
|
| 7999 |
-
"follower_count":
|
| 8000 |
-
"post_count":
|
| 8001 |
"communities": [
|
| 8002 |
-
"
|
| 8003 |
-
"
|
| 8004 |
-
"memes"
|
| 8005 |
]
|
| 8006 |
},
|
| 8007 |
"author_violations": [
|
| 8008 |
{
|
| 8009 |
"type": "spam",
|
| 8010 |
"date": "2026-03-01",
|
| 8011 |
-
"severity": "medium"
|
|
|
|
| 8012 |
},
|
| 8013 |
{
|
| 8014 |
"type": "spam",
|
| 8015 |
-
"date": "2026-02-
|
| 8016 |
-
"severity": "low"
|
|
|
|
| 8017 |
},
|
| 8018 |
{
|
| 8019 |
"type": "spam",
|
| 8020 |
-
"date": "2026-02-
|
| 8021 |
-
"severity": "low"
|
|
|
|
| 8022 |
}
|
| 8023 |
],
|
| 8024 |
"thread_context": null,
|
| 8025 |
-
"community_rules": "
|
| 8026 |
"linked_content_summary": null,
|
| 8027 |
"similar_precedents": null,
|
| 8028 |
"reporter_credibility": null
|
|
@@ -8038,7 +8044,7 @@
|
|
| 8038 |
"context_needed": [
|
| 8039 |
"author_violations"
|
| 8040 |
],
|
| 8041 |
-
"explanation": "
|
| 8042 |
}
|
| 8043 |
},
|
| 8044 |
{
|
|
@@ -8047,53 +8053,55 @@
|
|
| 8047 |
"category": "repeat_offender",
|
| 8048 |
"content_item": {
|
| 8049 |
"post_id": "p_41935",
|
| 8050 |
-
"text": "
|
| 8051 |
-
"author_id": "
|
| 8052 |
-
"community": "
|
| 8053 |
"timestamp": "2026-02-15T22:59:00Z",
|
| 8054 |
-
"media_type": "text",
|
| 8055 |
-
"media_description":
|
| 8056 |
},
|
| 8057 |
"trigger_info": {
|
|
|
|
|
|
|
| 8058 |
"report_categories": [],
|
| 8059 |
"sample_report_reason": null,
|
| 8060 |
"original_decision": null,
|
| 8061 |
"appeal_text": null,
|
| 8062 |
-
"audit_reason": null
|
| 8063 |
-
"trigger_type": "auto_flag",
|
| 8064 |
-
"auto_flag_reason": "spam_score: 0.6"
|
| 8065 |
},
|
| 8066 |
"available_context": {
|
| 8067 |
"author_profile": {
|
| 8068 |
-
"bio": "
|
| 8069 |
-
"account_age_days":
|
| 8070 |
-
"follower_count":
|
| 8071 |
-
"post_count":
|
| 8072 |
"communities": [
|
| 8073 |
-
"
|
| 8074 |
-
"
|
| 8075 |
-
"memes"
|
| 8076 |
]
|
| 8077 |
},
|
| 8078 |
"author_violations": [
|
| 8079 |
{
|
| 8080 |
"type": "spam",
|
| 8081 |
"date": "2026-03-01",
|
| 8082 |
-
"severity": "medium"
|
|
|
|
| 8083 |
},
|
| 8084 |
{
|
| 8085 |
"type": "spam",
|
| 8086 |
-
"date": "2026-02-
|
| 8087 |
-
"severity": "low"
|
|
|
|
| 8088 |
},
|
| 8089 |
{
|
| 8090 |
"type": "spam",
|
| 8091 |
-
"date": "2026-02-
|
| 8092 |
-
"severity": "low"
|
|
|
|
| 8093 |
}
|
| 8094 |
],
|
| 8095 |
"thread_context": null,
|
| 8096 |
-
"community_rules": "
|
| 8097 |
"linked_content_summary": null,
|
| 8098 |
"similar_precedents": null,
|
| 8099 |
"reporter_credibility": null
|
|
@@ -8109,7 +8117,7 @@
|
|
| 8109 |
"context_needed": [
|
| 8110 |
"author_violations"
|
| 8111 |
],
|
| 8112 |
-
"explanation": "
|
| 8113 |
}
|
| 8114 |
},
|
| 8115 |
{
|
|
@@ -8449,33 +8457,31 @@
|
|
| 8449 |
"category": "medical_content",
|
| 8450 |
"content_item": {
|
| 8451 |
"post_id": "p_44682",
|
| 8452 |
-
"text": "
|
| 8453 |
-
"author_id": "
|
| 8454 |
-
"community": "
|
| 8455 |
"timestamp": "2026-02-16T18:18:00Z",
|
| 8456 |
"media_type": "text",
|
| 8457 |
"media_description": null
|
| 8458 |
},
|
| 8459 |
"trigger_info": {
|
|
|
|
|
|
|
| 8460 |
"report_categories": [],
|
| 8461 |
"sample_report_reason": null,
|
| 8462 |
"original_decision": null,
|
| 8463 |
"appeal_text": null,
|
| 8464 |
-
"audit_reason": null
|
| 8465 |
-
"trigger_type": "auto_flag",
|
| 8466 |
-
"auto_flag_reason": "medical_content_detected"
|
| 8467 |
},
|
| 8468 |
"available_context": {
|
| 8469 |
"author_profile": {
|
| 8470 |
-
"bio": "
|
| 8471 |
"account_age_days": 456,
|
| 8472 |
-
"follower_count":
|
| 8473 |
-
"post_count":
|
| 8474 |
"communities": [
|
| 8475 |
-
"
|
| 8476 |
-
"
|
| 8477 |
-
"art",
|
| 8478 |
-
"finance"
|
| 8479 |
]
|
| 8480 |
},
|
| 8481 |
"author_violations": [],
|
|
@@ -8497,7 +8503,7 @@
|
|
| 8497 |
"context_needed": [
|
| 8498 |
"community_rules"
|
| 8499 |
],
|
| 8500 |
-
"explanation": "
|
| 8501 |
}
|
| 8502 |
},
|
| 8503 |
{
|
|
@@ -8506,36 +8512,38 @@
|
|
| 8506 |
"category": "medical_content",
|
| 8507 |
"content_item": {
|
| 8508 |
"post_id": "p_92842",
|
| 8509 |
-
"text": "
|
| 8510 |
-
"author_id": "
|
| 8511 |
-
"community": "
|
| 8512 |
"timestamp": "2026-02-28T21:05:00Z",
|
| 8513 |
-
"media_type": "text",
|
| 8514 |
-
"media_description":
|
| 8515 |
},
|
| 8516 |
"trigger_info": {
|
| 8517 |
-
"
|
| 8518 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8519 |
"original_decision": null,
|
| 8520 |
"appeal_text": null,
|
| 8521 |
-
"audit_reason": null
|
| 8522 |
-
"trigger_type": "auto_flag",
|
| 8523 |
-
"auto_flag_reason": "medical_content_detected"
|
| 8524 |
},
|
| 8525 |
"available_context": {
|
| 8526 |
"author_profile": {
|
| 8527 |
-
"bio": "
|
| 8528 |
"account_age_days": 823,
|
| 8529 |
-
"follower_count":
|
| 8530 |
-
"post_count":
|
| 8531 |
"communities": [
|
| 8532 |
-
"
|
| 8533 |
-
"
|
| 8534 |
]
|
| 8535 |
},
|
| 8536 |
"author_violations": [],
|
| 8537 |
"thread_context": null,
|
| 8538 |
-
"community_rules": "
|
| 8539 |
"linked_content_summary": null,
|
| 8540 |
"similar_precedents": null,
|
| 8541 |
"reporter_credibility": null
|
|
@@ -8552,7 +8560,7 @@
|
|
| 8552 |
"context_needed": [
|
| 8553 |
"community_rules"
|
| 8554 |
],
|
| 8555 |
-
"explanation": "
|
| 8556 |
}
|
| 8557 |
},
|
| 8558 |
{
|
|
@@ -9183,33 +9191,34 @@
|
|
| 9183 |
"category": "trusted_borderline",
|
| 9184 |
"content_item": {
|
| 9185 |
"post_id": "p_91512",
|
| 9186 |
-
"text": "
|
| 9187 |
-
"author_id": "
|
| 9188 |
"community": "books",
|
| 9189 |
"timestamp": "2026-03-14T22:30:00Z",
|
| 9190 |
"media_type": "text",
|
| 9191 |
"media_description": null
|
| 9192 |
},
|
| 9193 |
"trigger_info": {
|
|
|
|
|
|
|
| 9194 |
"report_categories": [
|
| 9195 |
"toxicity"
|
| 9196 |
],
|
| 9197 |
-
"sample_report_reason":
|
| 9198 |
"original_decision": null,
|
| 9199 |
"appeal_text": null,
|
| 9200 |
-
"audit_reason": null
|
| 9201 |
-
"trigger_type": "user_report",
|
| 9202 |
-
"report_count": 3
|
| 9203 |
},
|
| 9204 |
"available_context": {
|
| 9205 |
"author_profile": {
|
| 9206 |
-
"bio": "
|
| 9207 |
-
"account_age_days":
|
| 9208 |
-
"follower_count":
|
| 9209 |
-
"post_count":
|
| 9210 |
"communities": [
|
| 9211 |
-
"
|
| 9212 |
-
"
|
|
|
|
| 9213 |
]
|
| 9214 |
},
|
| 9215 |
"author_violations": [],
|
|
@@ -9230,7 +9239,7 @@
|
|
| 9230 |
"context_needed": [
|
| 9231 |
"author_profile"
|
| 9232 |
],
|
| 9233 |
-
"explanation": "
|
| 9234 |
}
|
| 9235 |
},
|
| 9236 |
{
|
|
|
|
| 7907 |
"category": "repeat_offender",
|
| 7908 |
"content_item": {
|
| 7909 |
"post_id": "p_97156",
|
| 7910 |
+
"text": "Built a tiny browser extension that color-codes Jira tickets. Free beta link here if anyone wants to try it.",
|
| 7911 |
+
"author_id": "buildinpublic_557",
|
| 7912 |
+
"community": "productivity",
|
| 7913 |
"timestamp": "2026-03-02T16:14:00Z",
|
| 7914 |
+
"media_type": "text+link",
|
| 7915 |
+
"media_description": "Promotional post linking to the author's own product page"
|
| 7916 |
},
|
| 7917 |
"trigger_info": {
|
| 7918 |
+
"trigger_type": "auto_flag",
|
| 7919 |
+
"auto_flag_reason": "spam_score: 0.6",
|
| 7920 |
"report_categories": [],
|
| 7921 |
"sample_report_reason": null,
|
| 7922 |
"original_decision": null,
|
| 7923 |
"appeal_text": null,
|
| 7924 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 7925 |
},
|
| 7926 |
"available_context": {
|
| 7927 |
"author_profile": {
|
| 7928 |
+
"bio": "Solo dev shipping tiny workflow tools",
|
| 7929 |
+
"account_age_days": 540,
|
| 7930 |
+
"follower_count": 980,
|
| 7931 |
+
"post_count": 233,
|
| 7932 |
"communities": [
|
| 7933 |
+
"productivity",
|
| 7934 |
+
"buildinpublic"
|
| 7935 |
]
|
| 7936 |
},
|
| 7937 |
"author_violations": [
|
| 7938 |
{
|
| 7939 |
"type": "spam",
|
| 7940 |
"date": "2026-03-01",
|
| 7941 |
+
"severity": "medium",
|
| 7942 |
+
"notes": "Previous borderline launch post removed after moderator warning."
|
| 7943 |
},
|
| 7944 |
{
|
| 7945 |
"type": "spam",
|
| 7946 |
+
"date": "2026-02-18",
|
| 7947 |
+
"severity": "low",
|
| 7948 |
+
"notes": "Cross-posted the same launch link across multiple communities."
|
| 7949 |
},
|
| 7950 |
{
|
| 7951 |
"type": "spam",
|
| 7952 |
+
"date": "2026-02-05",
|
| 7953 |
+
"severity": "low",
|
| 7954 |
+
"notes": "Repeated self-promotion after being directed to community promo thread."
|
| 7955 |
}
|
| 7956 |
],
|
| 7957 |
"thread_context": null,
|
| 7958 |
+
"community_rules": "Productivity communities allow occasional resource sharing, but repeated self-promotion and launch spam are prohibited.",
|
| 7959 |
"linked_content_summary": null,
|
| 7960 |
"similar_precedents": null,
|
| 7961 |
"reporter_credibility": null
|
|
|
|
| 7971 |
"context_needed": [
|
| 7972 |
"author_violations"
|
| 7973 |
],
|
| 7974 |
+
"explanation": "The surface post is plausibly useful and not an instant removal on text alone. The author's repeated prior self-promotional violations make this a repeat-offender spam case, so the correct move is to request violation history and remove it."
|
| 7975 |
}
|
| 7976 |
},
|
| 7977 |
{
|
|
|
|
| 7980 |
"category": "repeat_offender",
|
| 7981 |
"content_item": {
|
| 7982 |
"post_id": "p_99874",
|
| 7983 |
+
"text": "Turned my interview spreadsheet into a short paid guide. Posting the launch link in case it helps job seekers here.",
|
| 7984 |
+
"author_id": "resumebuilder_440",
|
| 7985 |
+
"community": "careers",
|
| 7986 |
"timestamp": "2026-03-02T23:21:00Z",
|
| 7987 |
+
"media_type": "text+link",
|
| 7988 |
+
"media_description": "Promotional post linking to the author's own product page"
|
| 7989 |
},
|
| 7990 |
"trigger_info": {
|
| 7991 |
+
"trigger_type": "auto_flag",
|
| 7992 |
+
"auto_flag_reason": "spam_score: 0.6",
|
| 7993 |
"report_categories": [],
|
| 7994 |
"sample_report_reason": null,
|
| 7995 |
"original_decision": null,
|
| 7996 |
"appeal_text": null,
|
| 7997 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 7998 |
},
|
| 7999 |
"available_context": {
|
| 8000 |
"author_profile": {
|
| 8001 |
+
"bio": "Career coach | Hiring manager notes",
|
| 8002 |
+
"account_age_days": 870,
|
| 8003 |
+
"follower_count": 1840,
|
| 8004 |
+
"post_count": 401,
|
| 8005 |
"communities": [
|
| 8006 |
+
"careers",
|
| 8007 |
+
"jobsearch"
|
|
|
|
| 8008 |
]
|
| 8009 |
},
|
| 8010 |
"author_violations": [
|
| 8011 |
{
|
| 8012 |
"type": "spam",
|
| 8013 |
"date": "2026-03-01",
|
| 8014 |
+
"severity": "medium",
|
| 8015 |
+
"notes": "Previous paid guide self-promo removed after moderator warning."
|
| 8016 |
},
|
| 8017 |
{
|
| 8018 |
"type": "spam",
|
| 8019 |
+
"date": "2026-02-18",
|
| 8020 |
+
"severity": "low",
|
| 8021 |
+
"notes": "Cross-posted the same launch link across multiple communities."
|
| 8022 |
},
|
| 8023 |
{
|
| 8024 |
"type": "spam",
|
| 8025 |
+
"date": "2026-02-05",
|
| 8026 |
+
"severity": "low",
|
| 8027 |
+
"notes": "Repeated self-promotion after being directed to community promo thread."
|
| 8028 |
}
|
| 8029 |
],
|
| 8030 |
"thread_context": null,
|
| 8031 |
+
"community_rules": "Careers communities allow occasional resource sharing, but repeated self-promotion and launch spam are prohibited.",
|
| 8032 |
"linked_content_summary": null,
|
| 8033 |
"similar_precedents": null,
|
| 8034 |
"reporter_credibility": null
|
|
|
|
| 8044 |
"context_needed": [
|
| 8045 |
"author_violations"
|
| 8046 |
],
|
| 8047 |
+
"explanation": "The surface post is plausibly useful and not an instant removal on text alone. The author's repeated prior self-promotional violations make this a repeat-offender spam case, so the correct move is to request violation history and remove it."
|
| 8048 |
}
|
| 8049 |
},
|
| 8050 |
{
|
|
|
|
| 8053 |
"category": "repeat_offender",
|
| 8054 |
"content_item": {
|
| 8055 |
"post_id": "p_41935",
|
| 8056 |
+
"text": "Compiled my freelance pitching lessons into a small ebook. Sharing the release link for anyone stuck finding first clients.",
|
| 8057 |
+
"author_id": "pitchcraft_173",
|
| 8058 |
+
"community": "writing",
|
| 8059 |
"timestamp": "2026-02-15T22:59:00Z",
|
| 8060 |
+
"media_type": "text+link",
|
| 8061 |
+
"media_description": "Promotional post linking to the author's own product page"
|
| 8062 |
},
|
| 8063 |
"trigger_info": {
|
| 8064 |
+
"trigger_type": "auto_flag",
|
| 8065 |
+
"auto_flag_reason": "spam_score: 0.6",
|
| 8066 |
"report_categories": [],
|
| 8067 |
"sample_report_reason": null,
|
| 8068 |
"original_decision": null,
|
| 8069 |
"appeal_text": null,
|
| 8070 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 8071 |
},
|
| 8072 |
"available_context": {
|
| 8073 |
"author_profile": {
|
| 8074 |
+
"bio": "Freelance editor and writing mentor",
|
| 8075 |
+
"account_age_days": 612,
|
| 8076 |
+
"follower_count": 1260,
|
| 8077 |
+
"post_count": 317,
|
| 8078 |
"communities": [
|
| 8079 |
+
"writing",
|
| 8080 |
+
"freelance"
|
|
|
|
| 8081 |
]
|
| 8082 |
},
|
| 8083 |
"author_violations": [
|
| 8084 |
{
|
| 8085 |
"type": "spam",
|
| 8086 |
"date": "2026-03-01",
|
| 8087 |
+
"severity": "medium",
|
| 8088 |
+
"notes": "Previous ebook self-promo removed after moderator warning."
|
| 8089 |
},
|
| 8090 |
{
|
| 8091 |
"type": "spam",
|
| 8092 |
+
"date": "2026-02-18",
|
| 8093 |
+
"severity": "low",
|
| 8094 |
+
"notes": "Cross-posted the same launch link across multiple communities."
|
| 8095 |
},
|
| 8096 |
{
|
| 8097 |
"type": "spam",
|
| 8098 |
+
"date": "2026-02-05",
|
| 8099 |
+
"severity": "low",
|
| 8100 |
+
"notes": "Repeated self-promotion after being directed to community promo thread."
|
| 8101 |
}
|
| 8102 |
],
|
| 8103 |
"thread_context": null,
|
| 8104 |
+
"community_rules": "Writing communities allow occasional resource sharing, but repeated self-promotion and launch spam are prohibited.",
|
| 8105 |
"linked_content_summary": null,
|
| 8106 |
"similar_precedents": null,
|
| 8107 |
"reporter_credibility": null
|
|
|
|
| 8117 |
"context_needed": [
|
| 8118 |
"author_violations"
|
| 8119 |
],
|
| 8120 |
+
"explanation": "The surface post is plausibly useful and not an instant removal on text alone. The author's repeated prior self-promotional violations make this a repeat-offender spam case, so the correct move is to request violation history and remove it."
|
| 8121 |
}
|
| 8122 |
},
|
| 8123 |
{
|
|
|
|
| 8457 |
"category": "medical_content",
|
| 8458 |
"content_item": {
|
| 8459 |
"post_id": "p_44682",
|
| 8460 |
+
"text": "Week three on sertraline and the nausea finally eased up. Posting the symptom timeline that helped me stay calm.",
|
| 8461 |
+
"author_id": "recoverylog_686",
|
| 8462 |
+
"community": "health",
|
| 8463 |
"timestamp": "2026-02-16T18:18:00Z",
|
| 8464 |
"media_type": "text",
|
| 8465 |
"media_description": null
|
| 8466 |
},
|
| 8467 |
"trigger_info": {
|
| 8468 |
+
"trigger_type": "auto_flag",
|
| 8469 |
+
"auto_flag_reason": "medical_content_detected",
|
| 8470 |
"report_categories": [],
|
| 8471 |
"sample_report_reason": null,
|
| 8472 |
"original_decision": null,
|
| 8473 |
"appeal_text": null,
|
| 8474 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 8475 |
},
|
| 8476 |
"available_context": {
|
| 8477 |
"author_profile": {
|
| 8478 |
+
"bio": "Anxiety-recovery journal | not a clinician",
|
| 8479 |
"account_age_days": 456,
|
| 8480 |
+
"follower_count": 211,
|
| 8481 |
+
"post_count": 84,
|
| 8482 |
"communities": [
|
| 8483 |
+
"health",
|
| 8484 |
+
"mentalhealth"
|
|
|
|
|
|
|
| 8485 |
]
|
| 8486 |
},
|
| 8487 |
"author_violations": [],
|
|
|
|
| 8503 |
"context_needed": [
|
| 8504 |
"community_rules"
|
| 8505 |
],
|
| 8506 |
+
"explanation": "The post describes the author's own medication side effects and recovery timeline without instructing others to change treatment. Community rules make this permissible first-person medical context rather than harmful advice."
|
| 8507 |
}
|
| 8508 |
},
|
| 8509 |
{
|
|
|
|
| 8512 |
"category": "medical_content",
|
| 8513 |
"content_item": {
|
| 8514 |
"post_id": "p_92842",
|
| 8515 |
+
"text": "Posting day-by-day photos from my ACL surgery recovery because a few people asked what the swelling looked like after week one.",
|
| 8516 |
+
"author_id": "acljournal_186",
|
| 8517 |
+
"community": "surgeryrecovery",
|
| 8518 |
"timestamp": "2026-02-28T21:05:00Z",
|
| 8519 |
+
"media_type": "text+image",
|
| 8520 |
+
"media_description": "Recovery photos documenting bruising and swelling after knee surgery"
|
| 8521 |
},
|
| 8522 |
"trigger_info": {
|
| 8523 |
+
"trigger_type": "auto_flag",
|
| 8524 |
+
"auto_flag_reason": "medical_content_detected",
|
| 8525 |
+
"report_categories": [
|
| 8526 |
+
"graphic_content"
|
| 8527 |
+
],
|
| 8528 |
+
"sample_report_reason": "Graphic medical recovery photos",
|
| 8529 |
"original_decision": null,
|
| 8530 |
"appeal_text": null,
|
| 8531 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 8532 |
},
|
| 8533 |
"available_context": {
|
| 8534 |
"author_profile": {
|
| 8535 |
+
"bio": "Physical therapy patient sharing recovery milestones",
|
| 8536 |
"account_age_days": 823,
|
| 8537 |
+
"follower_count": 344,
|
| 8538 |
+
"post_count": 128,
|
| 8539 |
"communities": [
|
| 8540 |
+
"surgeryrecovery",
|
| 8541 |
+
"physicaltherapy"
|
| 8542 |
]
|
| 8543 |
},
|
| 8544 |
"author_violations": [],
|
| 8545 |
"thread_context": null,
|
| 8546 |
+
"community_rules": "Recovery communities allow medically relevant photos when clearly educational or support-oriented, but prohibit shock posting and gore without context.",
|
| 8547 |
"linked_content_summary": null,
|
| 8548 |
"similar_precedents": null,
|
| 8549 |
"reporter_credibility": null
|
|
|
|
| 8560 |
"context_needed": [
|
| 8561 |
"community_rules"
|
| 8562 |
],
|
| 8563 |
+
"explanation": "The post shares recovery images in a support context for others undergoing similar surgery. Because the content is educational and community-specific rather than gratuitous, the correct decision is to approve it after checking the community rules."
|
| 8564 |
}
|
| 8565 |
},
|
| 8566 |
{
|
|
|
|
| 9191 |
"category": "trusted_borderline",
|
| 9192 |
"content_item": {
|
| 9193 |
"post_id": "p_91512",
|
| 9194 |
+
"text": "If you are going to post beginner questions, at least read the pinned guide before dumping this garbage on the feed.",
|
| 9195 |
+
"author_id": "archivist_150",
|
| 9196 |
"community": "books",
|
| 9197 |
"timestamp": "2026-03-14T22:30:00Z",
|
| 9198 |
"media_type": "text",
|
| 9199 |
"media_description": null
|
| 9200 |
},
|
| 9201 |
"trigger_info": {
|
| 9202 |
+
"trigger_type": "user_report",
|
| 9203 |
+
"report_count": 3,
|
| 9204 |
"report_categories": [
|
| 9205 |
"toxicity"
|
| 9206 |
],
|
| 9207 |
+
"sample_report_reason": "Needlessly hostile reply to a new member",
|
| 9208 |
"original_decision": null,
|
| 9209 |
"appeal_text": null,
|
| 9210 |
+
"audit_reason": null
|
|
|
|
|
|
|
| 9211 |
},
|
| 9212 |
"available_context": {
|
| 9213 |
"author_profile": {
|
| 9214 |
+
"bio": "Volunteer reading-list curator | answers newbie threads every week",
|
| 9215 |
+
"account_age_days": 1640,
|
| 9216 |
+
"follower_count": 2860,
|
| 9217 |
+
"post_count": 4210,
|
| 9218 |
"communities": [
|
| 9219 |
+
"books",
|
| 9220 |
+
"literature",
|
| 9221 |
+
"reading"
|
| 9222 |
]
|
| 9223 |
},
|
| 9224 |
"author_violations": [],
|
|
|
|
| 9239 |
"context_needed": [
|
| 9240 |
"author_profile"
|
| 9241 |
],
|
| 9242 |
+
"explanation": "The speaker is a trusted contributor, which makes the boundary-setting context relevant, but the phrasing still becomes dismissive and insulting. A warning is appropriate because it is low-severity toxicity rather than a removal-level attack."
|
| 9243 |
}
|
| 9244 |
},
|
| 9245 |
{
|