# CODEOWNERS-Based Team Assignment

## How It Works

When you upload a CODEOWNERS file, Luciq maps your crash reports to the right team automatically based on where the crash happened in your code.

Here's what happens under the hood:

1. **Team Mapping**: Team names from your CODEOWNERS file are matched to your existing teams on the Luciq dashboard. This matching is flexible since it's case-insensitive and treats hyphens, underscores, and spaces as the same thing. So `@org/my-team` will match a team called "My Team" without any extra configuration.
2. **Frame Selection**: When a crash comes in, Luciq looks at the crashed thread and picks the **top application frame** (the first frame that belongs to your code, not system libraries). The file path from that frame is what gets used for team matching.
3. **Path Matching**: That file path is compared against the paths in your CODEOWNERS rules. The matching works on path segments (split by `/`), so a rule for `LibraryA` will match any crash in `LibraryA/SomeFile.swift`, `LibraryA/SubDir/AnotherFile.swift`, etc.
4. **Specificity-Based Resolution**: When multiple rules match the same crash, Luciq picks the **most specific** one. Specificity is determined by the number of path segments in the matching rule — more segments means a more specific match. See [Specificity-Based Matching](#specificity-based-matching) below for details.

## CODEOWNERS File Example

A CODEOWNERS file lives in your repository and defines which team owns which part of the codebase. Here's what a typical one looks like:

```
# Each line maps a path pattern to a team
# The format is: <path>    <team>

# Networking layer owned by the platform team
/Sources/Networking/                    @org/platform-team

# Authentication module owned by the identity team
/Sources/Auth/                          @org/identity-team

# Checkout and payments owned by the commerce team
/Sources/Checkout/                      @org/commerce-team
/Sources/Payments/                      @org/commerce-team

# Everything under the analytics module
/Sources/Analytics/                     @org/data-team
```

With this file uploaded, if a crash happens in `Sources/Checkout/CartViewController.swift`, Luciq will automatically assign it to **Commerce Team**. A crash in `Sources/Auth/LoginManager.swift` goes to **Identity Team**, and so on.

A team can own multiple paths (like the commerce team above owning both Checkout and Payments), and paths can be as broad as a top-level directory or as specific as a single file.

{% hint style="warning" %}
**Don't Mix Files and Directories for the Same Team**

When defining ownership rules for the same team, avoid mixing file paths and directory paths. If a team has both file-level and directory-level rules, only the file-level rules will be used for assignment.

**Workaround**: Use only directories or only files for the same team — don't mix both.
{% endhint %}

## Specificity-Based Matching

When multiple ownership rules match the same crash, Luciq uses **specificity** to determine which team gets assigned. The rule with the most path segments wins.

### How Specificity Is Calculated

Specificity is based on the number of segments in the matching path token, where segments are separated by `/` (for file paths) or `.` (for Android packages).

| Rule token                     | Segments | Specificity |
| ------------------------------ | -------- | ----------- |
| `Sources`                      | 1        | 1           |
| `Sources/Networking`           | 2        | 2           |
| `Sources/Networking/WebSocket` | 3        | 3           |

### Example

Consider the following ownership definitions:

| Team           | Rule                                        |
| -------------- | ------------------------------------------- |
| Platform Team  | Path matches `Sources/Networking`           |
| Real-Time Team | Path matches `Sources/Networking/WebSocket` |

If a crash occurs in `Sources/Networking/WebSocket/ConnectionManager.swift`:

* **Platform Team** matches with specificity **2** (`Sources/Networking` has 2 segments)
* **Real-Time Team** matches with specificity **3** (`Sources/Networking/WebSocket` has 3 segments)

**Result**: The crash is assigned to **Real-Time Team** because it has the more specific rule.

### Tie-Breaking

When two rules have the **same specificity** (same number of path segments), the rule that was **most recently updated** wins. This ensures that if you update a definition, it takes priority over older definitions with the same level of specificity.

### How It Works Across Platforms

Specificity-based matching applies across all platforms:

| Platform         | Field             | Separator | Example                             |
| ---------------- | ----------------- | --------- | ----------------------------------- |
| **iOS**          | Path              | `/`       | `Controllers/Auth` → 2 segments     |
| **Android**      | Package           | `.`       | `com.example.app.auth` → 4 segments |
| **Flutter**      | Flutter Path      | `/`       | `lib/features/auth` → 3 segments    |
| **React Native** | React Native Path | `/`       | `src/screens/Auth` → 3 segments     |

For **filename-based** rules (as opposed to path/package), the specificity is always **1** regardless of the filename. This means path-based rules will generally take precedence over filename-based rules when both match.

## How to Test

To verify that team assignment is working correctly for your CODEOWNERS setup, keep in mind that Luciq needs **server-side symbolication** to extract file paths from crash frames, and that only happens when dSYMs are available.

Here's what you need to do:

1. **Build in Release mode**: Debug builds don't generate dSYM files. You need to archive or build your app in Release configuration for Xcode to produce them.
2. **Upload your dSYMs**: Once you have the dSYM files, upload them to Luciq (either manually through the dashboard or via your CI/CD pipeline). Without dSYMs, Luciq can't resolve the file paths needed for team matching.
3. **Trigger a crash**: Run the Release build, trigger a crash, and relaunch the app so the crash report gets sent.

{% hint style="warning" %}
**SDK-Side Symbolication**

If the SDK sends crashes that are already symbolicated (i.e., the stack frames already contain file paths and line numbers from the SDK side), server-side symbolication is skipped, and team assignment will not happen. This is why testing with a proper Release build and uploaded dSYMs is the correct flow.
{% endhint %}

Once the crash appears on your dashboard, you should see it assigned to the expected team based on your CODEOWNERS rules.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.luciq.ai/product-guides-and-integrations/product-guides/automation-and-workflows/team-ownership/codeowners-based-team-assignment.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
