Skip to content

Fallback to label name if label id not found#895

Merged
elie222 merged 7 commits intomainfrom
feat/fallback-to-name
Nov 3, 2025
Merged

Fallback to label name if label id not found#895
elie222 merged 7 commits intomainfrom
feat/fallback-to-name

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Nov 3, 2025

Summary by CodeRabbit

  • New Features

    • Fallback resolution of labels by name with automatic sync of resolved label IDs to stored rules; label operations scoped per email account.
  • Bug Fixes

    • Reduced failed labeling for Gmail and Outlook when label IDs are stale or missing.
  • Refactor

    • Label data unified to include both ID and name; onboarding now logs resolved label and folder details.
  • Chores

    • Version bumped to v2.17.28

@vercel
Copy link

vercel bot commented Nov 3, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
inbox-zero Ready Ready Preview Nov 3, 2025 3:27pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Threads label names and a scoped logger through labeling and onboarding flows; provider labelMessage gains name-based fallback and returns resolved IDs; adds labelMessageAndSync to sync stale label IDs into Action records; refactors reply-tracker to store full label objects per conversation status.

Changes

Cohort / File(s) Summary
Version Bump
version.txt
Bumps version from v2.17.27 to v2.17.28.
Provider types
apps/web/utils/email/types.ts
EmailProvider.labelMessage now accepts `labelName: string
Label sync helper
apps/web/utils/label.server.ts
New labelMessageAndSync(...): calls provider.labelMessage with labelName; when a fallback resolves a different ID, updates Action records scoped to emailAccountId to the resolved label ID and logs results.
Gmail label utilities
apps/web/utils/gmail/label.ts
New getOrCreateLabel({ gmail, name }) helper to fetch-or-create a Gmail label by name.
Gmail provider
apps/web/utils/email/google.ts, apps/web/utils/gmail/*
GmailProvider.labelMessage accepts labelName, attempts by ID then falls back to get-or-create by name; returns { usedFallback?, actualLabelId? }.
Outlook provider
apps/web/utils/email/microsoft.ts
OutlookProvider.labelMessage accepts labelName, tries lookup by ID then by name on miss, returns { usedFallback?, actualLabelId? }, and includes labelName in error messaging.
Label application entrypoints
apps/web/utils/ai/actions.ts, apps/web/utils/assistant/process-assistant-email.ts
Call sites updated to pass emailAccountId and use labelMessageAndSync(...); label collections now carry full label objects (id + name).
Onboarding / rule actions logging
apps/web/utils/actions/rule.ts
Threads a logger into getActionsFromCategoryAction/createRulesOnboardingAction and logs resolved label and folder names/IDs during onboarding create/update flows.
Reply-tracker label refactor
apps/web/utils/reply-tracker/label-helpers.ts, apps/web/utils/reply-tracker/label-helpers.test.ts
LabelIds → per-status objects { labelId, label }; getLabelIdsFromDbgetLabelsFromDb; removeConflictingThreadStatusLabels and applyThreadStatusLabel updated to use composite label objects and call labelMessageAndSync; tests updated to assert labelName passed.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Onboard UI
    participant Onboard as Onboarding Logic
    participant AI as Label Action
    participant Helper as labelMessageAndSync
    participant Provider as EmailProvider
    participant DB as Database (Action records)

    UI->>Onboard: create/update rule (passes logger)
    Onboard->>AI: resolve labelName & labelId (passes logger)
    AI->>Helper: labelMessageAndSync(provider, messageId, labelId, labelName, emailAccountId)
    Helper->>Provider: labelMessage(messageId, labelId, labelName)
    alt Provider finds label by ID
        Provider-->>Helper: { usedFallback: false, actualLabelId: id }
    else ID not found & name provided
        Provider-->>Helper: { usedFallback: true, actualLabelId: resolvedId }
        Helper->>DB: update Action.where(labelId==old && emailAccountId==X) -> set actualLabelId
        DB-->>Helper: update result
    else failure
        Provider-->>Helper: throw error (includes labelId & labelName)
    end
    Helper-->>AI: done
    AI-->>Onboard: logger.info recorded
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to consistency of the labelName parameter and { usedFallback?, actualLabelId? } return across types.ts, provider implementations, and all call sites.
  • Verify labelMessageAndSync database update selector scopes updates to the correct emailAccountId and labelId.
  • Review reply-tracker changes for correct handling of the new per-status { labelId, label } shape and related tests.

Possibly related PRs

Suggested reviewers

  • mosesjames7271-svg

Poem

"I nibble names and hop on logs, 🐇
Swapping stale IDs through fields and bogs,
I sync each trace and mend the trail,
A tiny rabbit fixing mail,
Soft hops, fresh labels — tidy tale."

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Fallback to label name if label id not found' directly and accurately describes the main purpose of the changeset. The changes implement a fallback mechanism across multiple email provider integrations (Gmail, Outlook) and helper utilities that attempt to resolve labels by name when the label ID lookup fails. This is the primary feature introduced throughout the modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/fallback-to-name

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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2a7844 and 4f3e9a4.

📒 Files selected for processing (7)
  • apps/web/utils/actions/rule.ts (7 hunks)
  • apps/web/utils/ai/actions.ts (1 hunks)
  • apps/web/utils/assistant/process-assistant-email.ts (1 hunks)
  • apps/web/utils/email/microsoft.ts (1 hunks)
  • apps/web/utils/email/types.ts (1 hunks)
  • apps/web/utils/reply-tracker/label-helpers.ts (7 hunks)
  • version.txt (1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • version.txt
  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • version.txt
  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/actions/**/*.ts

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/utils/actions/**/*.ts: Use server actions for all mutations (create/update/delete operations)
next-safe-action provides centralized error handling
Use Zod schemas for validation on both client and server
Use revalidatePath in server actions for cache invalidation

apps/web/utils/actions/**/*.ts: Use server actions (with next-safe-action) for all mutations (create/update/delete operations); do NOT use POST API routes for mutations.
Use revalidatePath in server actions to invalidate cache after mutations.

Files:

  • apps/web/utils/actions/rule.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/actions/*.ts

📄 CodeRabbit inference engine (.cursor/rules/server-actions.mdc)

apps/web/utils/actions/*.ts: Implement all server actions using the next-safe-action library for type safety, input validation, context management, and error handling. Refer to apps/web/utils/actions/safe-action.ts for client definitions (actionClient, actionClientUser, adminActionClient).
Use actionClientUser when only authenticated user context (userId) is needed.
Use actionClient when both authenticated user context and a specific emailAccountId are needed. The emailAccountId must be bound when calling the action from the client.
Use adminActionClient for actions restricted to admin users.
Access necessary context (like userId, emailAccountId, etc.) provided by the safe action client via the ctx object in the .action() handler.
Server Actions are strictly for mutations (operations that change data, e.g., creating, updating, deleting). Do NOT use Server Actions for data fetching (GET operations). For data fetching, use dedicated GET API Routes combined with SWR Hooks.
Use SafeError for expected/handled errors within actions if needed. next-safe-action provides centralized error handling.
Use the .metadata({ name: "actionName" }) method to provide a meaningful name for monitoring. Sentry instrumentation is automatically applied via withServerActionInstrumentation within the safe action clients.
If an action modifies data displayed elsewhere, use revalidatePath or revalidateTag from next/cache within the action handler as needed.

Server action files must start with use server

Files:

  • apps/web/utils/actions/rule.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/actions/rule.ts
  • apps/web/utils/assistant/process-assistant-email.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/ai/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features

Files:

  • apps/web/utils/ai/actions.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Files:

  • apps/web/utils/ai/actions.ts
🧠 Learnings (6)
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use descriptive scoped loggers for each feature

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Log inputs and outputs with appropriate log levels and include relevant context

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-07-18T15:05:34.899Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.899Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')

Applied to files:

  • apps/web/utils/email/types.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use TypeScript types for all parameters and return values in LLM features

Applied to files:

  • apps/web/utils/email/types.ts
📚 Learning: 2025-07-17T04:19:57.099Z
Learnt from: edulelis
Repo: elie222/inbox-zero PR: 576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.

Applied to files:

  • apps/web/utils/email/types.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
🧬 Code graph analysis (4)
apps/web/utils/actions/rule.ts (2)
apps/web/utils/logger.ts (1)
  • Logger (5-5)
apps/web/app/api/outlook/webhook/logger.ts (1)
  • logger (3-3)
apps/web/utils/assistant/process-assistant-email.ts (2)
apps/web/utils/types.ts (1)
  • isDefined (8-10)
apps/web/app/api/outlook/webhook/logger.ts (1)
  • logger (3-3)
apps/web/utils/email/microsoft.ts (1)
apps/web/app/api/outlook/webhook/logger.ts (1)
  • logger (3-3)
apps/web/utils/reply-tracker/label-helpers.ts (3)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
  • ConversationStatus (10-14)
apps/web/utils/email/types.ts (1)
  • EmailProvider (44-237)
apps/web/utils/rule/consts.ts (1)
  • getRuleLabel (122-124)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Analyze (javascript-typescript)

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 7 files

Prompt for AI agents (all 2 issues)

Understand the root cause of the following 2 issues and fix them.


<file name="apps/web/utils/reply-tracker/label-helpers.ts">

<violation number="1" location="apps/web/utils/reply-tracker/label-helpers.ts:54">
`dbLabels[type]` is always a truthy object (even when `labelId` is null), so this guard never runs and we stop looking up provider labels—conflicting status labels will no longer be removed.</violation>

<violation number="2" location="apps/web/utils/reply-tracker/label-helpers.ts:123">
Because `targetLabel` is always a non-null object, this branch no longer runs when the DB lacks the label; we skip the fallback lookup/creation and fail to apply the thread status label.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
apps/web/utils/reply-tracker/label-helpers.ts (1)

120-155: Enhance label resolution before applying.

Similar to the removal logic issue, when dbLabels[systemType] has a label name but no labelId, the code skips the provider lookup (line 124 checks both fields) and proceeds to call provider.labelMessage with labelId: "" and the label name. While the PR title indicates this fallback is intended, it's more robust to resolve the missing ID from providerLabels before applying, ensuring consistency and reducing reliance on provider-specific empty-ID handling.

Consider resolving missing fields from provider labels:

 let targetLabel = dbLabels[systemType];

 // If we don't have both labelId and label from DB, fetch/create it
 if (!targetLabel.labelId && !targetLabel.label) {
   const label =
     providerLabels.find((l) => l.name === getRuleLabel(systemType)) ||
     (await provider.createLabel(getRuleLabel(systemType)));
   if (label) {
     targetLabel = {
       labelId: label.id,
       label: label.name,
     };
   }
 }
+
+// If we have label name but missing ID, resolve from provider
+if (!targetLabel.labelId && targetLabel.label) {
+  const label = providerLabels.find((l) => l.name === targetLabel.label);
+  if (label) {
+    targetLabel = {
+      labelId: label.id,
+      label: label.name,
+    };
+  }
+}

 // Error only if we still don't have either field after attempting to fetch/create
 if (!targetLabel.labelId && !targetLabel.label) {
   logger.error("Failed to get or create target label");
   return;
 }

 return provider
   .labelMessage({
     messageId,
-    labelId: targetLabel.labelId || "",
+    labelId: targetLabel.labelId ?? "",
     labelName: targetLabel.label,
   })

Also replaced || with ?? for clearer null-coalescing semantics.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f3e9a4 and 17a8c18.

📒 Files selected for processing (1)
  • apps/web/utils/reply-tracker/label-helpers.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/reply-tracker/label-helpers.ts
🧠 Learnings (7)
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Implement fallbacks for AI failures

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : System prompt should define the LLM's role and task specifications

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-20T09:03:06.318Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-20T09:03:06.318Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use proper error types and logging for failures

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.{ts,tsx} : Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
🧬 Code graph analysis (1)
apps/web/utils/reply-tracker/label-helpers.ts (3)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
  • ConversationStatus (10-14)
apps/web/utils/email/types.ts (1)
  • EmailProvider (44-237)
apps/web/utils/rule/consts.ts (1)
  • getRuleLabel (122-124)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Jit Security
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
apps/web/utils/reply-tracker/label-helpers.ts (4)

11-17: LGTM! Type definition supports fallback strategy.

The enriched structure storing both labelId and label enables the intended fallback behavior when one field is missing.


19-46: Function signature updated correctly.

The parameter name and type changes align with the new label structure. Logger initialization follows coding guidelines.


94-118: Function setup looks good.

Direct fetching of dbLabels and providerLabels is appropriate for this function's usage pattern. Logger initialization follows coding guidelines.


172-206: Function correctly extracts partial label data.

The logic at line 197 stores label objects when either labelId or label is present, enabling partial-data scenarios. This is correct for faithfully representing DB state, but as noted in earlier comments, the calling functions should be enhanced to resolve missing fields from provider labels before using them.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

Reviewed changes from recent commits (found 2 issues).

2 issues found across 1 file

Prompt for AI agents (all 2 issues)

Understand the root cause of the following 2 issues and fix them.


<file name="apps/web/utils/reply-tracker/label-helpers.ts">

<violation number="1" location="apps/web/utils/reply-tracker/label-helpers.ts:54">
Named labels without an ID skip provider lookup, so conflicting status labels with name-only are never resolved/removed; attempt provider resolution whenever labelId is missing</violation>

<violation number="2" location="apps/web/utils/reply-tracker/label-helpers.ts:145">
Avoid passing an empty labelId into provider.labelMessage; if the provider doesn’t support name fallback this will fail; resolve the labelId or guard the call when only a name is available</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
apps/web/utils/reply-tracker/label-helpers.ts (3)

54-69: Critical: Labels with names but no IDs are never resolved or removed.

The condition at line 55 checks !label.labelId && !label.label, which only resolves labels when both fields are missing. When a label has a label (name) but no labelId (e.g., after migrations or partial saves), the provider lookup at lines 56-64 is skipped, and then line 65's check !label.labelId causes a continue, so the label is never added to removeLabelIds. This breaks the removal of conflicting status labels.

Apply this fix to resolve IDs whenever they're missing:

     let label = dbLabels[type as ConversationStatus];
-    if (!label.labelId && !label.label) {
+    if (!label.labelId) {
       const l = providerLabels.find((l) => l.name === getRuleLabel(type));
       if (!l?.id) {
         continue;
       }
       label = {
         labelId: l.id,
         label: l.name,
       };
     }
-    if (!label.labelId) {
-      continue;
-    }
-    removeLabelIds.push(label.labelId);
+    
+    if (label.labelId) {
+      removeLabelIds.push(label.labelId);
+    }

122-141: Critical: Missing label ID resolution when name exists.

The condition at line 125 only triggers label fetch/creation when both labelId and label are missing. If targetLabel has a label (name) but no labelId (common after migrations), the fetch/create block is skipped, and at line 146 an empty string is passed as labelId. This breaks label application for entries with names but missing IDs.

Fix by always attempting to resolve the ID when it's missing:

     let targetLabel = dbLabels[systemType];

-    // If we don't have both labelId and label from DB, fetch/create it
-    if (!targetLabel.labelId && !targetLabel.label) {
+    // If we don't have labelId from DB, resolve/create it
+    if (!targetLabel.labelId) {
       const label =
-        providerLabels.find((l) => l.name === getRuleLabel(systemType)) ||
+        providerLabels.find((l) => 
+          l.name === (targetLabel.label ?? getRuleLabel(systemType))
+        ) ||
         (await provider.createLabel(getRuleLabel(systemType)));
       if (label) {
         targetLabel = {
           labelId: label.id,
           label: label.name,
         };
       }
     }

-    // Error only if we still don't have either field after attempting to fetch/create
-    if (!targetLabel.labelId && !targetLabel.label) {
+    // Error only if we still don't have labelId after attempting to fetch/create
+    if (!targetLabel.labelId) {
       logger.error("Failed to get or create target label");
       return;
     }

143-155: Critical: Empty string passed as labelId causes provider failures.

Line 146 passes targetLabel.labelId || "" to labelMessageAndSync, which means an empty string is sent when labelId is null. Even though providers have fallback support via labelName, passing an empty string (rather than a valid ID or ensuring the ID is resolved first) is semantically incorrect and may cause failures depending on provider implementation.

The fix above (ensuring labelId is always resolved before reaching this call) would prevent empty strings from being passed. Alternatively, validate before calling:

+    if (!targetLabel.labelId) {
+      logger.error("Cannot apply label without labelId");
+      return;
+    }
+
     return labelMessageAndSync({
       provider,
       messageId,
-      labelId: targetLabel.labelId || "",
+      labelId: targetLabel.labelId,
       labelName: targetLabel.label,
       emailAccountId,
     }).catch((error) =>
🧹 Nitpick comments (2)
apps/web/utils/gmail/label.ts (1)

251-263: Trim the label name before reuse.

We already reject empty names based on trim(), but we still pass the original name (with possible leading/trailing whitespace) into getLabel/createLabel. That can create labels whose stored names include stray spaces, or fail to match existing labels with normalized names. Capture the trimmed value once and use it throughout to avoid duplicating labels with superficial whitespace differences.

 export async function getOrCreateLabel({
   gmail,
   name,
 }: {
   gmail: gmail_v1.Gmail;
   name: string;
 }) {
-  if (!name?.trim()) throw new Error("Label name cannot be empty");
-  const label = await getLabel({ gmail, name });
+  const trimmedName = name?.trim();
+  if (!trimmedName) throw new Error("Label name cannot be empty");
+  const label = await getLabel({ gmail, name: trimmedName });
   if (label) return label;
-  const createdLabel = await createLabel({ gmail, name });
+  const createdLabel = await createLabel({ gmail, name: trimmedName });
   return createdLabel;
 }
apps/web/utils/label.server.ts (1)

13-25: Consider validating input parameters.

The function accepts labelId: string and labelName: string | null but doesn't validate that at least one is meaningful. If labelId is an empty string and labelName is null, the provider call at line 34 may fail. Consider adding a guard or documenting the expected input contract.

 }): Promise<void> {
+  if (!labelId && !labelName) {
+    throw new Error("Either labelId or labelName must be provided");
+  }
+
   const logger = createScopedLogger("label.server").with({
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17a8c18 and 676ea4c.

📒 Files selected for processing (8)
  • apps/web/utils/ai/actions.ts (3 hunks)
  • apps/web/utils/assistant/process-assistant-email.ts (4 hunks)
  • apps/web/utils/email/google.ts (2 hunks)
  • apps/web/utils/email/microsoft.ts (2 hunks)
  • apps/web/utils/email/types.ts (1 hunks)
  • apps/web/utils/gmail/label.ts (1 hunks)
  • apps/web/utils/label.server.ts (1 hunks)
  • apps/web/utils/reply-tracker/label-helpers.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/utils/assistant/process-assistant-email.ts
🧰 Additional context used
📓 Path-based instructions (11)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
apps/web/utils/gmail/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/gmail-api.mdc)

Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')

Files:

  • apps/web/utils/gmail/label.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
apps/web/utils/ai/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features

Files:

  • apps/web/utils/ai/actions.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Files:

  • apps/web/utils/ai/actions.ts
🧠 Learnings (21)
📚 Learning: 2025-07-18T15:05:34.899Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.899Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')

Applied to files:

  • apps/web/utils/gmail/label.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/label.server.ts
  • apps/web/utils/email/microsoft.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : System prompt should define the LLM's role and task specifications

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/label.server.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Implement fallbacks for AI failures

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-20T09:03:06.318Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-20T09:03:06.318Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.{ts,tsx} : Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use proper error types and logging for failures

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : User prompt should contain the actual data and context

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-08T13:14:07.449Z
Learnt from: elie222
Repo: elie222/inbox-zero PR: 537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Keep system prompts and user prompts separate

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Format prompt data consistently across similar functions

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Remove excessive whitespace and truncate long inputs in prompts

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-18T17:27:58.249Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.249Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific `emailAccountId` are needed. The `emailAccountId` must be bound when calling the action from the client.

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Place main LLM feature implementations under apps/web/utils/ai/

Applied to files:

  • apps/web/utils/ai/actions.ts
  • apps/web/utils/label.server.ts
📚 Learning: 2025-07-18T17:27:58.249Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.249Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `adminActionClient` for actions restricted to admin users.

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use TypeScript types for all parameters and return values in LLM features

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-18T15:04:30.467Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.467Z
Learning: Applies to apps/web/app/api/**/route.ts : Use `withEmailAccount` for email-account-level operations

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-19T17:50:28.270Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-19T17:50:28.270Z
Learning: The `utils` folder also contains core app logic such as Next.js Server Actions and Gmail API requests.

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-17T04:19:57.099Z
Learnt from: edulelis
Repo: elie222/inbox-zero PR: 576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.

Applied to files:

  • apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use descriptive scoped loggers for each feature

Applied to files:

  • apps/web/utils/label.server.ts
🧬 Code graph analysis (6)
apps/web/utils/gmail/label.ts (2)
apps/web/utils/outlook/label.ts (3)
  • getOrCreateLabel (145-157)
  • getLabel (130-143)
  • createLabel (79-119)
apps/web/utils/email/google.ts (1)
  • createLabel (466-479)
apps/web/utils/reply-tracker/label-helpers.ts (4)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
  • ConversationStatus (10-14)
apps/web/utils/email/types.ts (1)
  • EmailProvider (44-237)
apps/web/utils/rule/consts.ts (1)
  • getRuleLabel (122-124)
apps/web/utils/label.server.ts (1)
  • labelMessageAndSync (13-72)
apps/web/utils/email/google.ts (2)
apps/web/utils/email/microsoft.ts (1)
  • labelMessage (334-384)
apps/web/utils/gmail/label.ts (2)
  • labelMessage (129-145)
  • getOrCreateLabel (251-263)
apps/web/utils/ai/actions.ts (1)
apps/web/utils/label.server.ts (1)
  • labelMessageAndSync (13-72)
apps/web/utils/label.server.ts (2)
apps/web/utils/email/types.ts (1)
  • EmailProvider (44-237)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/email/microsoft.ts (1)
apps/web/app/api/outlook/webhook/logger.ts (1)
  • logger (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Jit Security
🔇 Additional comments (9)
apps/web/utils/ai/actions.ts (1)

108-114: Nice integration with the sync helper.

Routing label execution through labelMessageAndSync (and threading emailAccountId) ensures stale IDs heal automatically while preserving the lazy-migration path. Clean upgrade.

apps/web/utils/email/types.ts (1)

95-99: Contract update aligns with fallback metadata.

Extending the signature to carry labelName and return fallback details keeps the provider interface in sync with the new healing flow.

apps/web/utils/email/google.ts (1)

270-319: Fallback flow covers stale Gmail IDs.

Catching the “not found” error, resolving/creating by name, and returning usedFallback plus actualLabelId gives labelMessageAndSync everything it needs to repair persisted actions without hiding unexpected exceptions. Nicely done.

apps/web/utils/email/microsoft.ts (1)

334-384: Parity with Outlook fallback looks solid.

The ID→name fallback keeps Outlook labeling resilient and the returned metadata matches the shared contract, so downstream sync logic can behave consistently.

apps/web/utils/label.server.ts (3)

1-3: LGTM: Imports follow best practices.

Clean imports using import type for types, proper path aliases (@/utils), and correct Prisma import pattern.


26-32: LGTM: Proper logger initialization.

Correctly uses createScopedLogger at the function level with .with() to add context, as per coding guidelines.


34-71: LGTM: Fallback handling is well-implemented.

The function correctly detects when a label ID fallback occurred, logs the stale ID detection, and updates all affected Actions in the database. The intentional error catching without rethrowing (line 64-70) ensures the labeling operation succeeds even if the DB sync fails, which is appropriate.

apps/web/utils/reply-tracker/label-helpers.ts (2)

12-18: LGTM: Type definition supports the new label structure.

The LabelIds type appropriately models label data with both labelId and label fields, allowing for partial information where either field may be null.


173-207: LGTM: Label fetching correctly restructured.

The renamed getLabelsFromDb function properly initializes all status types with null values and populates them from the database, correctly handling cases where either labelId or label may be present.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 8 files

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/web/utils/reply-tracker/label-helpers.test.ts (1)

19-33: Consider asserting labelMessage return values.

The mock for labelMessage (line 21) returns undefined, but per the AI summary, the implementation now returns additional information (usedFallback and actualLabelId). If applyThreadStatusLabel uses these return values, consider updating the mock to return realistic values and adding assertions to verify the function handles the response correctly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42ee020 and c2cb81d.

📒 Files selected for processing (1)
  • apps/web/utils/reply-tracker/label-helpers.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.test.{ts,js}

📄 CodeRabbit inference engine (.cursor/rules/security.mdc)

Include security tests in your test suites to verify authentication, authorization, and error handling.

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{test,spec}.{js,jsx,ts,tsx}: Don't use export or module.exports in test files.
Don't use focused tests.
Don't use disabled tests.
Make sure the assertion function, like expect, is placed inside an it() function call.
Don't nest describe() blocks too deeply in test files.
Don't use focused tests.
Don't use disabled tests.
Don't use export or module.exports in test files.

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

**/*.test.{ts,tsx}: Use Vitest (vitest) as the testing framework
Colocate tests next to the file under test (e.g., dir/format.ts with dir/format.test.ts)
In tests, mock the server-only module with vi.mock("server-only", () => ({}));
When testing code that uses Prisma, mock it with vi.mock("@/utils/prisma") and use the mock from @/utils/__mocks__/prisma
Use provided helpers for mocks: import { getEmail, getEmailAccount, getRule } from @/__tests__/helpers
Each test should be independent
Use descriptive test names
Mock external dependencies in tests
Clean up mocks between tests (e.g., vi.clearAllMocks() in beforeEach)
Avoid testing implementation details; focus on observable behavior
Do not mock the Logger

Files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
🧠 Learnings (2)
📚 Learning: 2025-10-02T23:23:48.064Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-10-02T23:23:48.064Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Prefer existing helpers from @/__tests__/helpers.ts (getEmailAccount, getEmail, getRule, getMockMessage, getMockExecutedRule) over custom helpers

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
📚 Learning: 2025-09-20T18:24:34.280Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-09-20T18:24:34.280Z
Learning: Applies to **/*.test.{ts,tsx} : Use provided helpers for mocks: import `{ getEmail, getEmailAccount, getRule }` from `@/__tests__/helpers`

Applied to files:

  • apps/web/utils/reply-tracker/label-helpers.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test

@elie222 elie222 merged commit e8e26cc into main Nov 3, 2025
16 of 17 checks passed
@elie222 elie222 deleted the feat/fallback-to-name branch November 3, 2025 15:27
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

@coderabbitai coderabbitai bot mentioned this pull request Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments