## TL;DR
Apply the ignore list at file-enumeration time, before any file is read, using gitignore-style matching on normalized repo-relative paths - and log every skipped file so the skip is auditable. Ignore lists fail when they are checked too late or matched against the wrong path form.

## The problem

```text
review agent failed to apply its ignore list: flagged vendored code anyway: how to fix
```

## When to use
- Findings appear on vendor/, node_modules, or third-party directories
- Generated files (protobuf output, lockfiles-as-generated) get reviewed
- The ignore config exists but findings still show up
- Review budget is spent on files the team does not own

## When not to use
- The team disagrees about whether a path should be ignored (a policy decision, not an application bug)
- The ignore list itself is missing or empty (write one first)
- Findings on vendored code are intentional (a security audit of vendored deps)

## Steps

### 1. Collect the authoritative ignore set in one place
Merge the agent's config ignore list, `.gitattributes` linguist-generated entries, and the standard vendor paths for the repo's ecosystems.

```bash
git check-attr linguist-generated -- $(git diff --name-only origin/main...HEAD) | grep ': generated$'
```

Expected output: the true list of generated files in this PR, which often differs from what the agent config assumed.

### 2. Filter at enumeration time, before any file is read
Apply the ignore patterns when building the file list for the review, not as a post-filter on findings. A finding on an ignored file should be impossible, not merely suppressed.

Expected output: ignored files never enter the review pipeline at all.

### 3. Normalize paths before matching
Convert every path to repo-relative with forward slashes before matching. Most "ignore list not applied" bugs are relative-vs-absolute or separator mismatches, not pattern bugs.

Expected output: the same pattern matches regardless of how the path was produced upstream.

### 4. Log every skipped file in the run output
Print the skipped paths with the pattern that excluded them. Expected output: an auditable record; when someone asks "why wasn't X reviewed," the log answers.

### 5. Verify with a before/after file-list diff
Run the file lister, apply the filter, and diff the reviewed set against the raw changed-file list. Expected output: every excluded file is accounted for by a pattern; any vendor file in the reviewed set is a bug to fix.

## Tool compatibility
- git check-attr and .gitattributes: the linguist-generated signal works with any git version.
- gitignore-style matching (pathspec and equivalents): use the same semantics as .gitignore so patterns behave the way engineers expect.
- Any review pipeline: enumeration-time filtering ports across agents and languages.

## Variant phrasings

### review bot commented on generated code
Same fix. Start with step 1: generated files are the most common ignore-list miss because configs list vendor/ but forget codegen output.

### ignore list not working in code review bot
Check step 3 before rewriting patterns. Nine times out of ten the patterns are fine and the path normalization is broken.

### agent reviewed node_modules in the PR diff
node_modules should rarely be in a PR at all; if it is, the ignore list is the backstop. Also consider why the directory was committed.

## Why it happens
Ignore lists are usually written as an afterthought and applied as a post-filter - or applied to absolute paths while patterns were written for relative ones. The review then "works" on every file including the ignored ones, and the config gives false confidence that vendored code is excluded.

## Edge cases
- Vendored code with a real vulnerability: policy call. Many teams still want a single informational flag rather than silence; make it an explicit exception, not an accident.
- Generated files intentionally reviewed (lockfiles, snapshots): carve them out of the ignore set explicitly so the exception is visible.
- Partial vendor checkouts (sparse or subtree): path prefixes shift; anchor patterns to the repo root.
- Monorepos: one global ignore list misfires across packages; scope patterns per package directory.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ZfzR-MmpbFNVVzZpXXLG6Q
