Repository navigation
feat: retune AI moderation thresholds (ban at ≥0.95) - #21
Conversation
….76–0.94, ban ≥0.95
🤖 CodeAnt AI — Review Status
|
✅ Deploy Preview for moderaty ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughAI moderation now uses thirteen toxicity categories and revised score thresholds. Intermediate scores use YouTube rejection instead of deletion. Tests and application copy reflect the new behavior. A separate design example updates a lighting-plot threshold. ChangesAI Moderation
Lighting-Plot Documentation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ModerationPipeline
participant YouTubeModerationAPI
participant ReviewQueue
ModerationPipeline->>YouTubeModerationAPI: Ban comments with scores >= 0.95
ModerationPipeline->>YouTubeModerationAPI: Reject comments with scores 0.76-0.94
ModerationPipeline->>ReviewQueue: Queue comments with scores 0.51-0.75
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
User descriptionBehaviorNew AI score bands (
Replaces the old bands (<0.35 approve / 0.35–0.50 queue / 0.51–0.85 delete / >0.85 ban). Note the AI no longer hard-deletes at any score — the mid band is now Tests (test-first)
Docs/copy kept in sync
CodeAnt-AI DescriptionRetune AI moderation outcomes and raise the automatic ban threshold What Changed
Impact
💡 Usage GuideChecking Your Pull RequestEvery time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later. Talking to CodeAnt AIGot a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask: This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code. ExamplePreserve Org Learnings with CodeAntYou can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input: This helps CodeAnt AI learn and adapt to your team's coding style and standards. ExampleRetrigger reviewAsk CodeAnt AI to review the PR again, by typing: Check Your Repository HealthTo analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health. |
🏁 CodeAnt Quality Gate ResultsCommit: ✅ Overall Status: PASSEDQuality Gate Details
|
There was a problem hiding this comment.
Review Complete
This PR successfully implements the AI moderation threshold adjustments with comprehensive test coverage. The implementation is sound:
- Threshold constants updated correctly (ban ≥0.95, reject 0.76-0.94, queue 0.51-0.75, approve ≤0.50)
- Operator change from
>to>=for ban threshold is intentional and properly tested - Replace delete action with reject in mid-range band maintains consistency
- All 99 tests pass with boundary conditions covered (0.50/0.51/0.75/0.76/0.94/0.95)
- UI copy synchronized across all pages
- Documentation updated to match implementation
No defects found that would block merge.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | ✅ 6 (≤ 100 complexity) |
| Duplication | ✅ 0 (≤ 1 duplication) |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
PR Summary by QodoRetune AI moderation bands: approve ≤0.50, queue 0.51–0.75, reject 0.76–0.94, ban ≥0.95
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
There was a problem hiding this comment.
Pull Request Overview
This PR successfully implements the transition from six to thirteen toxicity categories and retunes the moderation thresholds as specified. The system now correctly handles author bans at scores ≥ 0.95 and rejects comments in the 0.76–0.94 range without deleting them, aligning with the new 'reject' strategy. Codacy analysis indicates that the code is up to standards.\n\nHowever, there is a critical inconsistency in the EXECUTION_PLAN documentation where the test mock for the scoring function only includes six categories. This mismatch will trigger a ModerationError in the updated validation logic. Additionally, the UI copy for the human review queue should be adjusted to include a mention of AI failures to ensure full technical accuracy for end users.
Test suggestions
- Score 0.50 results in approval\n- [x] Score 0.51 results in human review queue\n- [x] Score 0.75 results in human review queue\n- [x] Score 0.76 results in automatic rejection\n- [x] Score 0.94 results in automatic rejection\n- [x] Score 0.95 results in author ban\n- [x] Score 0.504 rounds down to 0.50 (approved)\n- [x] Score 0.506 rounds up to 0.51 (queued)\n- [x] AI failure results in human review queue
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| describe('scoreComment', () => { | ||
| it('M1: returns max of the six toxic categories', async () => { | ||
| it('M1: returns max of the thirteen toxic categories', async () => { | ||
| vi.stubGlobal('fetch', vi.fn(async () => okResponse({ harassment: 0.4, 'harassment/threatening': 0.1, hate: 0.9, 'hate/threatening': 0.1, violence: 0.1, 'violence/graphic': 0.1 }))); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
The mock response for test case M1 is missing 7 of the 13 required toxicity categories. According to the updated logic on line 932 and the M6 case, this missing data will cause a ModerationError. Update the mock to include all 13 categories to ensure the test passes.\n\nTry running the following prompt in your coding agent:\n> In EXECUTION_PLAN_YouTube_Comment_Moderator.md, update the scoreComment mock on line 923 to include all 13 toxicity categories (harassment, harassment/threatening, hate, hate/threatening, illicit, illicit/violent, self-harm, self-harm/intent, self-harm/instructions, sexual, sexual/minors, violence, violence/graphic) so it complies with the updated validation requirements.
|
|
||
| <h1>Review queue — {data.ch?.title}</h1> | ||
| <p class="page-sub">Borderline comments (AI score 0.35–0.50) waiting for your decision.</p> | ||
| <p class="page-sub">Borderline comments (AI score 0.51–0.75) waiting for your decision.</p> |
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: The help text here differs from the version specified in the Execution Plan and is technically incomplete. According to the logic in pipeline.ts (lines 111-128), this queue holds both borderline comments and those where AI scoring failed.\n\nConsider updating to:\nsuggestion\n<p class="page-sub">Borderline comments (AI score 0.51–0.75 or AI unavailable) waiting for your decision.</p>\n
Code Review by Qodo
Context used✅ Compliance rules (platform):
51 rules 1. PRODUCT.md uses spaces indentation
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@EXECUTION_PLAN_YouTube_Comment_Moderator.md`:
- Around line 60-61: Update the embedded moderation specification’s
TOXIC_CATEGORIES block and the M1 fixture to include all thirteen required
toxicity keys, adding illicit, illicit/violent, self-harm, self-harm/intent,
self-harm/instructions, sexual, and sexual/minors alongside the existing
categories. Ensure the missing-key validation uses this complete category set
while preserving the existing score and threshold behavior.
- Line 42: Update manual queue action handling to add a pending-action state to
comments and persist action_pending before any YouTube setModerationStatus or
deleteComment call. After the remote operation succeeds, finalize the comment
state and write the audit record; ensure pending actions remain recoverable
after failures.
In `@src/lib/server/pipeline.test.ts`:
- Around line 460-461: Add upper rounding-boundary cases to the pipeline tests
covering raw 0.755 as rejected with API action reject and reason “ai score
0.76”, and raw 0.945 as rejected with API action ban and reason “ai score 0.95”.
Ensure the assertions validate status, action, and reason so incorrect rounding
logic causes the tests to fail.
In `@src/routes/`(app)/channels/[id]/queue/+page.svelte:
- Line 44: Update the queue subtitle paragraph in the page markup to explicitly
state that the queue includes comments for which AI scoring is unavailable,
while retaining the existing borderline score-range description.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 43547457-2ffb-4fea-a8fb-b57c07d1b100
📒 Files selected for processing (7)
DESIGN.mdEXECUTION_PLAN_YouTube_Comment_Moderator.mdPRODUCT.mdsrc/lib/server/pipeline.test.tssrc/lib/server/pipeline.tssrc/routes/(app)/channels/[id]/queue/+page.sveltesrc/routes/+page.svelte
| 1. Lets a YouTube channel owner connect their channel via Google OAuth (scope `youtube.force-ssl`, offline access). The AES-256-GCM-encrypted refresh token is stored in the DB. | ||
| 2. Stores per-channel rules: keyword, regex (recheck-validated), or blocked-user, each mapping to `hold` | `reject` | `delete` | `ban`. | ||
| 3. Exposes `GET /api/cron?secret=<CRON_SECRET>` which processes **one channel per run** (least-recently-run first) and **one page of ≤100 comments per run**, with a persisted checkpoint (continuation token + high-water mark) so bursts larger than one page are drained across runs **without skipping comments**. Per comment: rule match first, then OpenAI Moderation. Score ≥ 0.85 → auto-reject; 0.35–0.85 → human review queue; < 0.35 → approved. Rule hits execute their configured action. **Every enforcement action is recorded in the DB (`action_pending`) BEFORE the YouTube write, then confirmed after** — a crash mid-run is reconciled on the next run, never repeated blindly and never lost. | ||
| 3. Exposes `GET /api/cron?secret=<CRON_SECRET>` which processes **one channel per run** (least-recently-run first) and **one page of ≤100 comments per run**, with a persisted checkpoint (continuation token + high-water mark) so bursts larger than one page are drained across runs **without skipping comments**. Per comment: rule match first, then OpenAI Moderation. Score ≥ 0.95 → auto-ban (reject + ban author); 0.76–0.94 → auto-reject; 0.51–0.75 → human review queue; ≤ 0.50 → approved. Rule hits execute their configured action. **Every enforcement action is recorded in the DB (`action_pending`) BEFORE the YouTube write, then confirmed after** — a crash mid-run is reconciled on the next run, never repeated blindly and never lost. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 8 'action_pending|pendingAction|setModerationStatus|deleteComment' src/routesRepository: Bonobo791/Moderaty
Length of output: 10428
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file='src/routes/(app)/channels/[id]/queue/+page.server.ts'
schema=$(rg -l 'pendingAction|action_pending' src/lib src/routes | head -n 1 || true)
printf '%s\n' '--- action implementation ---'
sed -n '45,75p' "$file"
printf '%s\n' '--- pending-action references ---'
rg -n -C 3 'pendingAction|action_pending' src/lib src/routes || true
printf '%s\n' '--- relevant schema fields ---'
rg -n -C 4 'comments|status|decidedBy|auditLog' src/lib/server/db/schema* src/lib/server/db 2>/dev/null | head -n 160
printf '%s\n' '--- plan references ---'
rg -n -C 5 'action_pending|pendingAction|Step 21|setModerationStatus|deleteComment' EXECUTION_PLAN_YouTube_Comment_Moderator.mdRepository: Bonobo791/Moderaty
Length of output: 24436
Implement DB-before-remote ordering for manual queue actions. The runtime calls YouTube before updating comments, and comments has no pendingAction field. Add the pending-action state, persist it before setModerationStatus or deleteComment, then finalize and audit after success.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@EXECUTION_PLAN_YouTube_Comment_Moderator.md` at line 42, Update manual queue
action handling to add a pending-action state to comments and persist
action_pending before any YouTube setModerationStatus or deleteComment call.
After the remote operation succeeds, finalize the comment state and write the
audit record; ensure pending actions remain recoverable after failures.
Source: Coding guidelines
| - Toxicity categories: `harassment`, `harassment/threatening`, `hate`, `hate/threatening`, `illicit`, `illicit/violent`, `self-harm`, `self-harm/intent`, `self-harm/instructions`, `sexual`, `sexual/minors`, `violence`, `violence/graphic`. Comment AI score = max of these thirteen. Spam is NOT an AI category; users catch spam with their own rules. | ||
| - Thresholds (fixed): AUTO_BAN = 0.95, AUTO_REJECT = 0.76, QUEUE = 0.51. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Update the embedded moderation specification to use all thirteen categories.
The revised contract requires thirteen keys, but the TOXIC_CATEGORIES block at Lines 528-535 and the M1 fixture at Lines 923-926 still enumerate only six. The missing-key requirement at Lines 932-941 would therefore validate only the old set. Add illicit, illicit/violent, self-harm, self-harm/intent, self-harm/instructions, sexual, and sexual/minors to the embedded implementation and fixture. The supplied src/lib/server/moderation.test.ts context already exercises sexual.
Also applies to: 241-241, 922-922, 932-941
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@EXECUTION_PLAN_YouTube_Comment_Moderator.md` around lines 60 - 61, Update the
embedded moderation specification’s TOXIC_CATEGORIES block and the M1 fixture to
include all thirteen required toxicity keys, adding illicit, illicit/violent,
self-harm, self-harm/intent, self-harm/instructions, sexual, and sexual/minors
alongside the existing categories. Ensure the missing-key validation uses this
complete category set while preserving the existing score and threshold
behavior.
| { raw: 0.506, status: 'pending', reason: 'ai score 0.51' }, | ||
| { raw: 0.504, status: 'approved', reason: 'ai score 0.50' } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
Add the upper rounding-boundary cases.
The changed cases cover only the lower transitions. Add raw 0.755 with status rejected, API action reject, and reason ai score 0.76. Add raw 0.945 with status rejected, API action ban, and reason ai score 0.95.
As per coding guidelines, tests must fail when the real logic is wrong.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lib/server/pipeline.test.ts` around lines 460 - 461, Add upper
rounding-boundary cases to the pipeline tests covering raw 0.755 as rejected
with API action reject and reason “ai score 0.76”, and raw 0.945 as rejected
with API action ban and reason “ai score 0.95”. Ensure the assertions validate
status, action, and reason so incorrect rounding logic causes the tests to fail.
Source: Coding guidelines
|
|
||
| <h1>Review queue — {data.ch?.title}</h1> | ||
| <p class="page-sub">Borderline comments (AI score 0.35–0.50) waiting for your decision.</p> | ||
| <p class="page-sub">Borderline comments (AI score 0.51–0.75) waiting for your decision.</p> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Mention AI-unavailable comments in the queue description.
src/lib/server/pipeline.ts places scoring failures in the pending queue. The execution plan also documents “or AI unavailable” at Line 1516. This subtitle names only the score range, so users can misinterpret AI-unavailable items.
Suggested copy
- <p class="page-sub">Borderline comments (AI score 0.51–0.75) waiting for your decision.</p>
+ <p class="page-sub">Borderline comments (AI score 0.51–0.75, or AI unavailable) waiting for your decision.</p>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <p class="page-sub">Borderline comments (AI score 0.51–0.75) waiting for your decision.</p> | |
| <p class="page-sub">Borderline comments (AI score 0.51–0.75, or AI unavailable) waiting for your decision.</p> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/routes/`(app)/channels/[id]/queue/+page.svelte at line 44, Update the
queue subtitle paragraph in the page markup to explicitly state that the queue
includes comments for which AI scoring is unavailable, while retaining the
existing borderline score-range description.
chore: PR #21 review follow-ups (plan-doc mock, queue copy)




Behavior
New AI score bands (
src/lib/server/pipeline.ts):pending, auditqueue)setModerationStatusrejected, no author ban)setModerationStatusrejected +banAuthor=true)Replaces the old bands (<0.35 approve / 0.35–0.50 queue / 0.51–0.85 delete / >0.85 ban). Note the AI no longer hard-deletes at any score — the mid band is now
reject(hidden, irreversible, same as the ban path minusbanAuthor).Tests (test-first)
npm run check,npm run buildall green.Docs/copy kept in sync
EXECUTION_PLAN_YouTube_Comment_Moderator.md: overview, fixed-thresholds list, pipeline snippet constants, M2 boundary row, queue-page copy, six → thirteen categories.PRODUCT.md: threshold bullet (also six → thirteen categories).DESIGN.md: example cue label ≥ 0.85 → ≥ 0.95.