Feature Proposal: AI-Powered Gemini Semantic Email Classifier - #492
Feature Proposal: AI-Powered Gemini Semantic Email Classifier#492don-petry wants to merge 55 commits into
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
🤖 CodeAnt AI — Review Status
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Gemini-powered Gmail classifier with configurable domains, response validation, retry handling, Gmail labeling, confidence-based filter creation, documentation, tests, coverage reporting, and repository maintenance updates. ChangesGmail AI classifier
Repository maintenance
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Gmail
participant Classifier
participant Gemini
participant AdvancedGmail
Gmail->>Classifier: Provide unprocessed thread
Classifier->>Gemini: Submit message details
Gemini-->>Classifier: Return category and confidence
Classifier->>Gmail: Apply category and Processed labels
Classifier->>AdvancedGmail: Create qualifying sender filter
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoAdd Proposal 001 for Gemini semantic email classifier + auto-filter engine
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
There was a problem hiding this comment.
Code Review
This pull request proposes a native Gemini AI Semantic Email Classifier & Auto-Filter Engine for the google-app-scripts suite. The feedback suggests aligning the proposed directory structure with the repository layout conventions in AGENTS.md by including a src/index.js file, and replacing LaTeX inline math syntax with standard unicode or plain text for better markdown rendering.
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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 `@docs/proposals/proposal-001-ai-gemini-semantic-classifier.md`:
- Line 25: Update the fenced code blocks for the architecture diagram and
file-tree sections in the proposal to specify the text language identifier,
using text immediately after each opening fence. Ensure both referenced blocks
are updated without changing their contents.
- Around line 36-38: Expand the classifier response contract in the Gemini
semantic classifier proposal around the “JSON Schema Classification” output:
define the exact response fields and types, permitted labels, confidence meaning
and range, and an explicit abstain/unknown outcome. Document schema validation
and the required behavior for malformed, refused, or invalid responses so filter
creation relies only on validated classifier results.
- Around line 30-31: Update the proposal’s time-driven trigger design to define
bounded batch processing, persisted checkpoints, execution locking, retry
behavior, and an idempotent operation order across Gmail search, classification,
label updates, attachment writes, and log appends. Specify how partial failures
and timeouts resume safely without repeating classifications or duplicating
attachments and logs, using the existing persisted-state flow in code.gs as the
reference pattern.
- Around line 14-19: Expand the proposal’s filter-generation flow around
“Self-Learning Gmail Filter Generation” and the corresponding implementation
details to require calibrated confidence, staged approval or quarantine for
risky senders, duplicate-filter detection, and label existence/resolution
handling before creating sender-wide filters. Define correction semantics so
manual label changes update or delete existing filters, and include rollback
behavior for previously created rules.
- Around line 4-19: Update the proposal’s implementation prerequisites to define
explicit user opt-in configuration, a data-minimization and redaction boundary
for sender, subject, and body content, Gemini provider data-retention
assumptions, API-key storage in user-only Google Apps Script properties, and the
required Gmail Advanced Service/API scopes before implementation.
- Line 6: Update the model identifiers in the proposal’s architecture
description to use one canonical, supported Gemini model, preferably
gemini-1.5-flash-to-250120; alternatively, explicitly document and validate the
fallback strategy for any secondary model. Remove the inconsistent
gemini-2.0-flash reference unless its API compatibility is established.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 2518aa63-6da3-44ec-8f76-c76bdb944bdb
📒 Files selected for processing (1)
docs/proposals/proposal-001-ai-gemini-semantic-classifier.md
Code Review by Qodo
Context used✅ Compliance rules (platform):
20 rules 1.
|
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-28T02:35:42Z. |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (4)
src/gmail-ai-classifier/tests/code.test.js (1)
11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrettier formatting violation.
🎨 Proposed fix
- canonicalDomains: ['01_Household/Primary_House', '04_Family_Health/Bowens'] + canonicalDomains: [ + '01_Household/Primary_House', + '04_Family_Health/Bowens', + ],🤖 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/gmail-ai-classifier/tests/code.test.js` at line 11, Format the canonicalDomains array according to the repository’s Prettier rules in the affected test fixture, preserving both existing domain values and their order.Source: Linters/SAST tools
src/gmail-ai-classifier/code.gs (2)
80-90: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueCheck the HTTP response code before parsing.
muteHttpExceptions: truemeans non-2xx Gemini responses (rate limits, invalid key, safety blocks) return error bodies without acandidatesarray, soparsed.candidates[0]throws a genericTypeErrorthat masks the real cause. Checkingresponse.getResponseCode()first would produce a clearer log for troubleshooting auth/quota issues.🤖 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/gmail-ai-classifier/code.gs` around lines 80 - 90, Update classifyWithGemini to check response.getResponseCode() immediately after UrlFetchApp.fetch and before parsing the body; for non-2xx responses, log the status and response details, then return null without accessing parsed.candidates. Preserve the existing parsing flow for successful responses.
29-32: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winThreads that fail classification never get labeled and stay in the queue indefinitely.
Since these threads never receive
processedLabel, they keep matchingconfig.unprocessedQueryon every future run, permanently occupying a slot in the 15-thread batch. Consider applying a distinct "error"/"unclassified" label so persistently-failing threads don't crowd out new ones.🤖 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/gmail-ai-classifier/code.gs` around lines 29 - 32, Update the classification-failure branch in processEmailsWithAiClassifier to apply a distinct error or unclassified label to the thread before returning. Reuse the existing label-management mechanism and preserve the current logging, ensuring failed threads no longer match config.unprocessedQuery while successfully classified threads retain their existing labeling flow.src/gmail-ai-classifier/config.gs (1)
6-7: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSilent placeholder fallback for the API key.
If
GEMINI_API_KEYisn't set in Script Properties, this silently falls back to the literal string'YOUR_GEMINI_API_KEY'rather than failing fast. Every classification call will then fail authentication, butclassifyWithGemini's catch-all swallows the error and returnsnull, so the whole classifier silently no-ops with no clear signal why.Consider throwing/logging a clear configuration error when the key is missing/placeholder instead of allowing it to propagate silently.
🤖 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/gmail-ai-classifier/config.gs` around lines 6 - 7, The geminiApiKey configuration currently accepts a placeholder value and allows authentication failures to be swallowed by classifyWithGemini. Validate the ScriptProperties value during configuration, reject missing or placeholder keys with a clear configuration error, and ensure classifyWithGemini does not silently suppress this configuration failure.
🤖 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 `@src/gmail-ai-classifier/code.gs`:
- Line 107: Update the success log in createGmailFilterRule to remove
cleanSender from the console.log arguments, while retaining the confirmation
that the permanent Gmail filter was created and the label information.
- Around line 9-21: Update processEmailsWithAiClassifier to sort the threads
returned by GmailApp.search by each thread’s last-message date before the
empty-check and forEach processing flow, using the existing Gmail thread/message
APIs and preserving the current processing behavior after sorting.
- Around line 16-46: Guard both label results from ensureUserLabel before
calling thread.addLabel: validate processedLabel before iterating, and validate
categoryLabel before adding it for each thread. Skip or safely handle the
affected operation when either value is null, while preserving processing of
subsequent threads and the existing behavior for valid labels.
- Around line 95-114: Update createGmailFilterRule to list existing Gmail
filters before calling Gmail.Users.Settings.Filters.create, and skip creation
when a filter already has the same sender criterion and target label action.
Preserve the current filter creation and logging behavior when no matching
filter exists.
In `@src/gmail-ai-classifier/config.gs`:
- Around line 12-16: Update the configuration object so unprocessedQuery is
constructed from the processedLabel value instead of hardcoding “Processed”;
ensure the resulting query continues excluding threads carrying the configured
processed label.
In `@src/gmail-ai-classifier/tests/code.test.js`:
- Around line 5-17: Replace the self-validating literal in the “returns standard
config schema” test with an invocation of the real getAiClassifierConfig
implementation. Export that function through the project’s Node-safe module
boundary (following the existing src/index.js/module.exports pattern), import it
in code.test.js, and inject any required globals through test wrappers so the
assertions validate the actual configuration behavior.
---
Nitpick comments:
In `@src/gmail-ai-classifier/code.gs`:
- Around line 80-90: Update classifyWithGemini to check
response.getResponseCode() immediately after UrlFetchApp.fetch and before
parsing the body; for non-2xx responses, log the status and response details,
then return null without accessing parsed.candidates. Preserve the existing
parsing flow for successful responses.
- Around line 29-32: Update the classification-failure branch in
processEmailsWithAiClassifier to apply a distinct error or unclassified label to
the thread before returning. Reuse the existing label-management mechanism and
preserve the current logging, ensuring failed threads no longer match
config.unprocessedQuery while successfully classified threads retain their
existing labeling flow.
In `@src/gmail-ai-classifier/config.gs`:
- Around line 6-7: The geminiApiKey configuration currently accepts a
placeholder value and allows authentication failures to be swallowed by
classifyWithGemini. Validate the ScriptProperties value during configuration,
reject missing or placeholder keys with a clear configuration error, and ensure
classifyWithGemini does not silently suppress this configuration failure.
In `@src/gmail-ai-classifier/tests/code.test.js`:
- Line 11: Format the canonicalDomains array according to the repository’s
Prettier rules in the affected test fixture, preserving both existing domain
values and their order.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: b9cfa103-3865-4261-8da9-b2bf52ff23e7
📒 Files selected for processing (5)
docs/proposals/proposal-001-ai-gemini-semantic-classifier.mdsrc/gmail-ai-classifier/README.mdsrc/gmail-ai-classifier/code.gssrc/gmail-ai-classifier/config.gssrc/gmail-ai-classifier/tests/code.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/proposals/proposal-001-ai-gemini-semantic-classifier.md
Dev-Lead — review-changes (applied)Changes committed and pushed. |
CI Failure: SonarCloud Code AnalysisStep: SonarCloud Scan (Quality Gate evaluation) The Quality Gate failed on a single condition: 0.0% Coverage on New Code (required ≥ 80%) for the new Suggested fix: Add a step in |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-29T23:16:21Z. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-29T23:18:53Z. |
Dev-Lead — fix-bot-comment (no-changes)Agent reasoning |
…ckground classification
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-29T23:33:22Z. |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-30T00:22:33Z. |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-30T04:07:09Z. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-30T04:10:10Z. |
Dev-Lead — fix-bot-comment (no-changes)Agent reasoning |
|
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
|
Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-07-30T04:23:45Z. |



User description
Ref #491. Adds Feature Proposal 001 for Native Gemini AI Semantic Email Classifier & Auto-Filter Engine.
Summary by CodeRabbit
CodeAnt-AI Description
Add Gemini-powered Gmail classification with automatic labeling, filtering, and GitHub summaries
What Changed
Processedlabel without removing messages from the Inbox.Impact
✅ Less manual Gmail sorting✅ Inbox-preserving email classification✅ Fewer duplicate sender filters✅ Fewer unclassified results after temporary API failures💡 Usage Guide
Checking Your Pull Request
Every 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 AI
Got 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.
Example
Preserve Org Learnings with CodeAnt
You 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.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To 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.