Commit Graph
687 Commits
Author SHA1 Message Date
MythEclipseandClaude Opus 4.8 edb55fb5bf fix(ai-moderation): add religious expression safe list to stop Astaghfirullah false positives
Common Indonesian religious expressions like 'Astaghfirullah', 'Astaga',
'Alhamdulillah', 'Subhanallah', dll were being flagged as vulgar_language
by the LLM. Added explicit rule that these are normal religious/cultural
expressions in Indonesia - not vulgar language - even in all-caps or
with repeated letters.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:52:31 +07:00
MythEclipseandClaude Opus 4.8 e6e44b30c7 fix(ai-moderation): remove indonesianTextNormalizer to stop hallucinated slang flags
The rule-based badword detector was injecting [normalized_text] and
[normalization_notes] tags into the LLM prompt that caused false
positive hallucinations - the LLM started associating innocent words
('sapik', 'furina') with furry/sexual_deviation due to misleading
context injected by the normalizer.

Removed:
- indonesianTextNormalizer.ts (full file deletion)
- formatModerationTextEvidenceForPrompt import/usage in llmModerationClient
- formatModerationTextEvidenceForPrompt import/usage in conversationContext
- stale re-exports in index.ts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:27:24 +07:00
MythEclipseandClaude Opus 4.8 cfe7230a55 fix(ai-moderation): prevent LLM from hallucinating furry slang on common names and unknown words
- Adds explicit rule that Indonesian names/nicknames like 'Sapik' (Syafik),
  'Ayang', 'Dek', 'Bang', 'Mas', etc. are NOT furry or sexual_deviation references
- Adds rule prohibiting the LLM from inventing slang meanings for words
  it doesn't recognize - default to innocent until proven guilty
- Prevents false positive cascade where LLM confuses names with furry slang

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:22:35 +07:00
MythEclipseandClaude Opus 4.8 817f1ce3df fix(ai-moderation): add Furina/Genshin character name exception to prevent false positive furry flags
Nama karakter game/anime populer seperti 'Furina' dari Genshin Impact
sering kena false positive sebagai 'sexual_deviation' karena kemiripan
fonetik dengan kata 'furry'. Menambahkan aturan eksplisit bahwa nama
karakter fiksi normal bukan referensi furry fetish, dgn pengecualian
jika konteks pesan secara eksplisit membahas aspek fetish/seksual.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 12:04:10 +07:00
MythEclipse 25c86dcc30 fix(ai-moderation): raise retry backoffs and cooldowns, make 429 retryable, reduce prompt false positives 2026-06-05 21:47:02 +07:00
MythEclipse d7a35e8377 refactor(ai-moderation): expand prompt rules for lyrics and literature
Update moderation guidelines to prevent false positives on song lyrics, poems, memes, and literary quotes, ensuring political or revolutionary content is not flagged as conflict instigation unless accompanied by explicit incitement.
2026-06-05 20:05:32 +07:00
MythEclipse 49ada183b2 feat(ai-moderation): implement auto-fallback for streaming and refine prompt rules
- Add automatic fallback to streaming mode if the provider rejects non-streaming requests with a 400 error
- Refactor `llmChat` to use an internal execution function to support retry logic with modified parameters
- Update moderation prompt to explicitly allow Japanese pop culture terms (e.g., "moe", "waifu", "wibu") to prevent false positive sexual deviation flags
2026-06-05 19:44:06 +07:00
MythEclipse bdf80b081c chore(ai-moderation): increase llm client timeout and add test script
- Increase OpenAI client timeout from 15s to 60s to handle high-latency models
- Add `test-llm.js` for manual verification of LLM connectivity and response times
2026-06-05 19:08:57 +07:00
MythEclipse 049582504e feat(ai-moderation): implement error handling and robust streaming for llmClient
Wrap the LLM completion logic in a try-catch block to provide detailed
error logging, including status codes and raw response data, when
API requests fail.

- Add comprehensive error logging for failed LLM API calls.
- Ensure streaming responses are correctly aggregated and returned
  even when wrapped in error handling logic.
2026-06-05 18:47:30 +07:00
MythEclipse c0a067322b refactor(ai-moderation): enhance llmClient flexibility and idempotency
Update the LLM client to support streaming responses and improve
database migration idempotency.

- Add `stream` support to `llmChat` with dynamic chunk parsing for
  compatibility across different LLM providers.
- Remove hardcoded default temperature and top_p to allow for more
  flexible parameter passing.
- Update database migrations to use `IF NOT EXISTS` for tables and
  indexes to prevent errors during re-runs.
2026-06-05 18:45:58 +07:00
MythEclipse 69b4916d08 docs(docs): remove obsolete mascot and microservices documentation
Removes outdated implementation guides and architecture documentation
related to the mascot chatbot and microservices setup.

- Delete `MASCOT_CHATBOT_GUIDE.md`
- Delete `MASCOT_IMPLEMENTATION.md`
- Delete `README_MICROSERVICES.md`
2026-06-05 18:22:42 +07:00
MythEclipse 42ea2924ac feat(db): add migrations for user reputation and channel culture tables
Adds new database schema migrations to support the implementation of
user reputation tracking and channel-specific culture context.

- Creates migration `0005_large_squadron_sinister.sql` containing
  `user_reputations` and `channel_cultures` tables.
- Updates Drizzle migration journal to include the new migration step.
- Adds `fix_prompt.py` utility for managing prompt adjustments.
2026-06-05 18:21:52 +07:00
MythEclipse 08c624fcf4 fix(ai-moderation): use generic sender name and force descriptive media analysis to prevent bad global cache poisoning 2026-06-05 18:20:43 +07:00
MythEclipse 2f3d7e1d61 feat(ai-moderation): introduce user reputation and channel culture context
Implements a context-aware moderation system by tracking user behavior
and channel-specific norms to improve AI decision-making accuracy.

- Adds `user_reputations` table to track trust scores, clean streaks,
  and infraction history.
- Adds `channel_cultures` table to store AI-generated summaries of
  channel-specific norms and slang.
- Implements `userReputationStore` to autonomously update user scores
  based on moderation outcomes (clean vs. flagged).
- Implements `cultureLearner` and `channelCultureStore` to manage
  evolving channel contexts.
- Enhances LLM prompts to inject user reputation (trust scores,
  history) and channel culture summaries, enabling "wisdom-based"
  moderation (e.g., giving benefit of the doubt to high-trust users).
- Integrates reputation and culture updates into the existing
  `aiAnalyzer` pipeline.
2026-06-05 18:04:57 +07:00
MythEclipse f057bf1f0b refactor(ai-moderation): implement distributed locking and content-based caching
Refactors the AI moderation pipeline to improve concurrency control and
cache efficiency by moving from user-centric to content-centric caching.

- Implements a distributed locking mechanism for media analysis using
  `acquireMediaAnalysisLock` to prevent redundant LLM vision calls across
  multiple pods.
- Transitions text moderation caching from `user_mod:userId:hash` to a
  purely content-based `text_mod:hash` approach to increase hit rates.
- Enhances `getPendingMessagesByConversation` with atomic transactions
  and `FOR UPDATE SKIP LOCKED` to safely transition messages from
  `pending` to `processing` state.
- Adds `processing` status to the `AIStatus` type and database schema to
  track active analysis lifecycles.
- Implements polling logic in `llmModerationClient.ts` to wait for
  in-progress media analyses.
2026-06-05 16:56:46 +07:00
MythEclipse 09f6e80ddd fix(ai-moderation): resolve race conditions and implement processing state
Introduces a `processing` state to the AI analysis lifecycle to prevent
duplicate processing of the same messages.

- Implements row-level locking using `FOR UPDATE SKIP LOCKED` in
  `messageStore.ts` to ensure atomic message acquisition.
- Adds a `processing` status to the `AIStatus` type and database schema.
- Fixes a TOCTOU race condition in `aiAnalyzer.ts` by synchronizing
  the conversation processing lock before async database operations.
- Implements `revertStuckProcessingMessages` to recover messages stuck
  in the `processing` state due to worker crashes or timeouts.
- Updates `processBatch` and scheduling logic to correctly manage and
  release conversation-level locks.
2026-06-05 16:36:14 +07:00
MythEclipse 399919ded0 feat(ai-moderation): add anti-evasion rule for emoji spelling
- Instructs the AI to decode combinations of regional indicator emojis (e.g., 🇬 🇦 🇾) and custom letters spelling out words, rather than dismissing them as 'just a series of emojis'
- Added a specific few-shot example (Contoh 15) to demonstrate flagging this technique when used to spell banned words
2026-06-05 16:23:59 +07:00
MythEclipse 6b3f2cdecd feat(ai-moderation): tighten rules for anatomical vulgarity and BL mentions
- Added explicit zero-tolerance rule for anatomical/sexual vulgarity (e.g. titten, kontol), explicitly forbidding the AI from passing them off as 'casual conversation' or 'jokes'
- Expanded sexual_deviation rule to explicitly cover brief mentions of BL (Boys Love), yaoi, yuri, and LGBT topics, instructing the AI to flag them regardless of casual context
2026-06-05 16:16:21 +07:00
MythEclipse e00b23f9b8 fix(concurrency): eliminate all identified double-queue and race conditions
Implements full audit from double_queue_audit.md.

## Critical

fix(backend): reanalyze-batch — per-scope in-flight guard (messages.routes.ts)
  Two concurrent admin sessions clicking 'Retry All Errors' simultaneously now
  get a 409 REANALYZE_BATCH_IN_PROGRESS for the same guildId:channelId scope.
  Prevents the recovery worker from being triggered twice for the same set of
  error messages.

fix(discord-gateway): messageUpdate embed resolution skip (messageCapture.ts)
  Discord fires messageUpdate when link previews resolve 1-2s after send
  even though the message body is unchanged. Compare newContent vs
  existingContent before resetting ai_status to pending and re-queueing LLM.
  Eliminates a spurious duplicate analysis that could overwrite a valid result.

## High

fix(discord-gateway): scheduleAutoDelete idempotency (aiAnalyzer.ts)
  Add autoDeleteInFlight Set. Both processBatch and processIndividualFallback
  call scheduleAutoDelete; without the guard, a message that races through
  both paths launches two concurrent attemptAutoDeleteFlaggedMessage calls,
  producing a duplicate moderation-action log entry and a Discord 10008 error.
  The Set is cleaned up in a .finally() block after each attempt completes.

## Medium

fix(frontend): revert optimistic pending state on HTTP failure (useMessages.ts)
  Capture the prior MessageRecord inside the setMessages functional updater
  (no extra useCallback deps needed). If reanalyzeMessage() throws, restore
  the snapshot so the UI reflects the real DB state instead of lying.

fix(discord-gateway): exclude individual_analysis_exhausted from recovery queries
  Both getConversationKeysWithIncompleteAnalysis and
  getIncompleteMessagesByConversation now add a NOT LIKE guard for
  individual_analysis_exhausted. Prevents an infinite recovery loop if a bug
  ever writes both flags to the same row.

## Low

fix(discord-gateway): unified timer path in scheduleConversationAnalysis
  Remove the separate cooldown-path that created a secondary timer calling
  scheduleConversationAnalysis recursively. Replace with a single
  clear-and-reset pattern where delayMs = max(cooldownRemainder+500, debounce).
  Eliminates the edge case where both timers were live simultaneously.

## Misc

fix(backend): cast req.params.id to String() to satisfy Express typings
  Pre-existing tsc error (string | string[]) exposed by our edit.
  String() is correct; route params are always scalar strings at runtime.
2026-06-05 16:09:23 +07:00
MythEclipse 5c0a837cf0 fix(ai-moderation): eliminate double-queue on failure and spam-retry
Three root causes patched:

1. aiAnalyzer.ts — processBatch apiFailedMessages path:
   After reverting messages to 'pending', suppress shouldScheduleNext
   (was true by default) to prevent scheduleConversationAnalysis from
   firing immediately and racing with the recovery worker that will pick
   up those same pending messages on its next poll cycle.
   Also release the conversationProcessing lock immediately after the
   revert so the cooldown timer (not the full processing-timeout) gates
   the next attempt.

2. messages.routes.ts — POST /messages/:id/reanalyze:
   Add a per-message reanalyzeInFlight Set.  Concurrent requests for
   the same ID now return HTTP 409 instead of issuing duplicate UPDATEs
   and triggering multiple recovery worker activations.
   Also narrow the SQL predicate to 'WHERE id =  AND ai_status != pending'
   so a click that arrives while the recovery worker already picked the
   message up is a no-op at the DB level.
2026-06-05 15:38:31 +07:00
MythEclipse a0bf7dfdd9 chore(ai-moderation): harden LLM prompt and lexical scanner against evasion techniques and cross-lingual vulgarities 2026-06-05 15:28:04 +07:00
MythEclipse 9a02ac8d17 feat(ai-moderation): flag excessive religious jokes and satire as sara 2026-06-04 19:31:08 +07:00
MythEclipse a965fb1e08 fix(moderation): treat age_restricted skipped messages as clean instead of error 2026-06-04 19:28:59 +07:00
MythEclipse d1d4510ce8 chore(format): auto-format files with biome 2026-06-04 18:52:56 +07:00
MythEclipse 367d8696c8 fix(moderation): revert API failures to pending instead of sticking in error state 2026-06-04 18:52:37 +07:00
MythEclipse 946343ec8c fix(ai-moderation): skip caching error results to prevent false positives from transient failures 2026-06-04 17:42:23 +07:00
MythEclipse 4996acfacf refactor(ai-moderation): unify worker pool entry points with discriminated union routing 2026-06-04 17:39:40 +07:00
MythEclipse 686dc2de4f refactor(ai-moderation): remove unused count variable in stale CB error pruning loop 2026-06-04 17:35:52 +07:00
MythEclipse 121b78198c feat(ai-moderation): add circuit breaker alert system with extensible handlers 2026-06-04 17:35:26 +07:00
MythEclipse 8c67eefede refactor(ai-moderation): offload individual message analysis to worker pool and add auto-delete notifications 2026-06-04 17:34:54 +07:00
MythEclipse ce8a42f5fd feat(ai-moderation): eliminate LLM-based badword detection in favor of pure rule-based matching 2026-06-04 17:33:08 +07:00
MythEclipse b3d42118bd fix(ai-moderation): use cached status instead of hardcoding "clean" for cache hit results 2026-06-04 17:30:37 +07:00
MythEclipse 9474d30cb7 refactor(ai-moderation): migrate sticker cache SQL queries from ? to $N parameter placeholders 2026-06-04 17:29:19 +07:00
MythEclipse 269a13d96a fix(ai-moderation): restrict vision cache pre-download check to stickers and custom emojis only 2026-06-04 17:20:52 +07:00
MythEclipse 5d9713b162 chore(config): update TELE_UPLOAD_URL domain across all services 2026-06-04 17:12:02 +07:00
MythEclipse aaebe168cf fix(ai-moderation): fallback to discord_url when uploaded_url is null for attachment images 2026-06-04 17:06:57 +07:00
MythEclipse fc52fe5c1d feat(ai-moderation): cache per-user moderation results for text-only messages to skip redundant LLM calls 2026-06-04 16:54:06 +07:00
MythEclipse c1e79dca23 feat(ai-moderation): add per-user moderation result cache for spammer deduplication 2026-06-04 16:51:08 +07:00
MythEclipse b0278de51a feat(ai-moderation): add URL analysis rules to moderation prompt to prevent domain-based false positives 2026-06-04 16:35:14 +07:00
MythEclipse 65a65fdf39 feat(ai-moderation): fetch web content from URLs in text-only messages for accurate LLM analysis 2026-06-04 16:32:08 +07:00
MythEclipse 0a35e83a6c refactor(analytics): replace hardcoded color tokens with theme-aware CSS variables 2026-06-04 14:17:45 +07:00
MythEclipse 3ecb7bd15c chore: session auto-commit 2026-06-04 14:16:59 +07:00
MythEclipse 458f20d5c3 chore: session auto-commit 2026-06-04 14:16:26 +07:00
MythEclipse ad61af54e8 refactor(analytics): replace TrendChart gradient bars with interactive SVG line chart featuring tooltips and grid lines 2026-06-04 14:15:56 +07:00
MythEclipse ceb5fc95ba refactor(analytics): replace gradient bars with interactive SVG donut and horizontal bar charts 2026-06-04 14:15:27 +07:00
MythEclipse 00001973d8 refactor(analytics): replace ActivityChart stacked bars with interactive SVG chart featuring tooltips and grid lines 2026-06-04 14:14:49 +07:00
MythEclipse 259b0babb5 feat(ai-moderation): parse moderation category from LLM fallback response instead of using static defaults 2026-06-04 13:49:35 +07:00
MythEclipse 3fc26592fc feat(ai-moderation): add simple text-only LLM fallback when normal analysis fails for small models 2026-06-04 13:40:25 +07:00
MythEclipse e55ee342b1 fix(ai-moderation): downgrade operational logs to debug and add missing debug logs to silent early-return paths 2026-06-04 13:13:55 +07:00
MythEclipse d568cab88f fix(ai-moderation): add defensive logging to silent failure paths in media analysis 2026-06-04 13:06:35 +07:00