feat(ingestion): respect .gitignore and .gitnexusignore during file discovery#231
Conversation
|
@ivkond is attempting to deploy a commit to the NexusCore Team on Vercel. A member of the Team first needs to authorize it. |
|
@ivkond, opened PR #301 combining |
|
Claude finished @magyargergo's task in 3m 51s —— View job Deep Analysis: PR #231 — Gaps, Architecture & Comparison with PR #301
Executive SummaryPR #231 is a solid, well-thought-out implementation with good test coverage and clean architecture. The 3-layer filter design is correct and extensible. I found 5 real bugs/gaps, 3 design concerns, and several test coverage gaps. For the future-proofing dimension, the architecture is good but has one important escape-hatch missing that should block merge. Bugs & Correctness Gaps1. Silent failure masks misconfigured
|
| Missing Test | Why It Matters |
|---|---|
.gitignore with bare-name directory pattern (local not local/) |
Covers Bug #3 above |
.gitnexusignore negation pattern (!vendor/) |
Should document/verify the limitation |
.gitignore with file-glob pattern (*.log) — tests only directory patterns |
Ensures file-level filtering works, not just directory pruning |
| Symlinks pointing into ignored directories | Edge case that real repos hit |
.gitignore with anchored patterns (/root-only-dir/) |
Anchoring is a gitignore feature the ignore package supports |
isIgnoredDirectory with gitignore-only dirs |
Would expose the misleading export issue (Bug #2) |
Permission error on .gitignore file |
Covers Bug #1 (silent failure) |
Architecture & Future-Proofing Assessment
What's good:
- The
IgnoreLikeinterface integration is correct and glob-version-stable childrenIgnoredfor true directory-level pruning (not just result filtering) is the right approach — avoidsstat()on ignored trees- Async factory pattern (
createIgnoreFilter) is clean and supports future async sources (network, git config reading) - The
ignorenpm package choice is correct — 30M weekly downloads, gitignore-spec compliant, handles negations/comments/globs
What limits future extensibility:
- Nested
.gitignorefiles would require threading theIgnoreinstance through recursive traversal — doable but requires changingcreateIgnoreFilter's interface - Per-directory ignore instances (needed for proper nested support) would require a different architecture than the current single-instance approach
- The
shouldIgnorePathfunction (extension/filename based filtering) is still called viaignored()on every file — if the filter is later extended to be configurable, this function's coupling to the filter complicates it
Verdict: The architecture correctly separates concerns and the extensibility points needed are reachable without breaking changes. The biggest blocker for "future proof" is the missing escape hatch (D1).
Comparison with PR #301
Based on @jecanore's comment: PR #301 uses a "single
.gitnexusignoreviaignorenpm package" and is "simpler to maximize merge likelihood"
| Dimension | PR #231 | PR #301 |
|---|---|---|
.gitignore support |
✅ Automatic, zero-config | ❌ Not included |
.gitnexusignore support |
✅ Yes | ✅ Yes |
| Scope | Ignore filtering only | Ignore + unsupported language fix |
| Implementation complexity | Higher (3-layer) | Lower (1 file, simpler) |
| Real-world problem solved | Grafana/Docker-mounted plugin case works out of box | Requires user to create .gitnexusignore duplicating .gitignore |
| Test coverage | 18 integration tests | Unknown |
| Merge risk | Slightly higher (more change) | Lower |
Recommendation: PR #231's approach is architecturally superior for the core problem. The real-world motivation (repo with 34% index pollution from gitignored directories) is exactly the case where automatic .gitignore respect is the right default. PR #301's single-file approach forces every affected user to manually create and maintain .gitnexusignore duplicating what's already in .gitignore.
That said, PR #301's bundling with an unsupported-language fix means merging #231 alone still leaves a separate PR outstanding. Ideal outcome: merge PR #231's ignore logic (it's the more complete implementation), and cherry-pick or re-apply the unsupported-language fix from #301 separately.
Summary: What Needs to Happen Before Merge
| Priority | Issue | Blocking? |
|---|---|---|
| 🔴 High | Add --no-gitignore escape hatch (env var or CLI flag) |
Yes — footgun risk |
| 🟡 Medium | Fix silent failure to distinguish ENOENT vs EACCES | Recommended |
| 🟡 Medium | Add test for bare-name directory patterns in .gitignore |
Recommended |
| 🟡 Medium | Document/rename isIgnoredDirectory to signal it's hardcoded-only |
Recommended |
| 🟢 Low | Memoize createIgnoreFilter per repoPath |
Nice-to-have |
| 🟢 Low | Add negation-pattern limitation notice to user docs | Nice-to-have |
CI Report✅ All checks passed Pipeline Status
Test Results
✅ All 2140 tests passed 17 test(s) skipped — expand for detailsIntegration:
Code CoverageCombined (Unit + Integration)
Coverage breakdown by test suiteUnit Tests
Integration Tests
📋 View full run · Generated by CI |
…iscovery Add support for excluding files from indexing based on .gitignore and .gitnexusignore patterns. Previously, GitNexus used only a hardcoded ignore list, causing significant index pollution in repositories with git-ignored directories containing code (e.g., Docker-mounted volumes). Changes: - Add `ignore` package for gitignore-spec pattern matching - Add `loadIgnoreRules()` to parse .gitignore + .gitnexusignore - Add `createIgnoreFilter()` returning glob-compatible IgnoreLike object - Integrate filter into glob's `ignore` option for directory-level pruning - Remove post-glob `.filter()` call (now handled during traversal) The hardcoded DEFAULT_IGNORE_LIST remains as fallback for non-git repos. Closes #228 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
e1b94ca to
f0fc601
Compare
Addressed review feedback and rebased onto upstream/mainChanges in
|
| "tree-sitter-python": "^0.21.0", | ||
| "tree-sitter-ruby": "^0.23.1", | ||
| "tree-sitter-rust": "^0.21.0", | ||
| "tree-sitter-swift": "^0.6.0", |
There was a problem hiding this comment.
Can you revert this line please?
- Distinguish ENOENT vs EACCES in loadIgnoreRules (warn on permission errors) - Add GITNEXUS_NO_GITIGNORE env var to bypass .gitignore parsing - Fix bare-name pattern matching in childrenIgnored (check both with/without trailing slash) - Rename isIgnoredDirectory to isHardcodedIgnoredDirectory for clarity - Add clarifying comments for design decisions (D2 negation, D3 dot:false redundancy) - Add tests for bare-name patterns, file-glob patterns, EACCES handling, env var Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f0fc601 to
6b580f2
Compare
|
@claude try to find gaps in this implementation and see use ultra-thinking if it maintains the architecture and it's future proof. |
|
Claude finished @magyargergo's task in 3m 51s —— View job Gap Analysis & Architecture Review — PR #231 (Post-Feedback State)
|
| Previous Issue | Status | Evidence |
|---|---|---|
| Silent ENOENT vs EACCES failure | ✅ Fixed | ignore-service.ts:272–277 — ENOENT skipped silently, others emit console.warn |
Bare-name pattern mismatch in childrenIgnored |
✅ Fixed | ignore-service.ts:314 — checks both ig.ignores(rel) and ig.ignores(rel + '/') |
Misleading isIgnoredDirectory name |
✅ Fixed | Renamed to isHardcodedIgnoredDirectory at line 250 |
No escape hatch for .gitignore |
✅ Fixed | GITNEXUS_NO_GITIGNORE env var at lines 262–265 |
| D2/D3 design intent undocumented | ✅ Fixed | Comments added at lines 194–197, 304–307 |
Remaining Gaps
G1. GITNEXUS_NO_GITIGNORE is undiscoverable — no documentation surface
The env var is implemented and tested, but it's not surfaced anywhere a user would look:
- Not in
gitnexus analyze --help - Not in README or any docs
- Not as a comment in generated
.gitnexusignore
A user whose .gitignore accidentally excludes source files has no way to know this escape hatch exists unless they read the source code. This defeats the purpose of the escape hatch.
G2. ignored() and childrenIgnored() use p.relative() without normalization
// ignore-service.ts:296, 313
const rel = p.relative();path-scurry's Path.relative() returns POSIX paths on all platforms, so this works on Windows. But this is an implicit contract — there's no guard or comment. If glob's path-scurry version changes this behavior, the ignore package will fail silently on Windows because it requires forward-slash paths. A one-line comment or explicit .replace(/\\/g, '/') guard would make this resilient.
G3. createIgnoreFilter env var is evaluated per-call, not per-process
// ignore-service.ts:263
const filenames = process.env.GITNEXUS_NO_GITIGNORE
? ['.gitnexusignore']
: ['.gitignore', '.gitnexusignore'];The env var is read inside loadIgnoreRules on every call. In a future watch-mode or incremental re-index scenario, if the env var changes between calls (unlikely but possible with test harnesses), behavior would be inconsistent within a run. Consider reading GITNEXUS_NO_GITIGNORE once at startup and passing it as a parameter — this also makes the function easier to unit-test without process.env mutation.
G4. Integration tests don't cover GITNEXUS_NO_GITIGNORE end-to-end
The unit tests cover the env var (lines 311–358 of ignore-service.test.ts), but no integration test verifies that walkRepositoryPaths correctly uses it. A directory that should be excluded via .gitignore should be included when GITNEXUS_NO_GITIGNORE=1 is set — this end-to-end path is untested.
G5. package-lock.json open review comment (line 38)
@magyargergo requested reverting line 38. After the rebase and force-push, line 38 in the current file is "tree-sitter-rust": "^0.21.0" — which is unchanged from origin/main. The actual PR-introduced change to this file is the "ignore": "^7.0.5" addition at line 24 and the corresponding node_modules/ignore block.
Likely the reviewer's line 38 reference was against the pre-rebase file and the lines shifted. Needs clarification with @magyargergo: is the concern about the ignore package being added as a dependency, or about something else? If the intent is to remove the ignore package entirely, the gitignore parsing would need to be implemented with manual pattern matching — significantly more complex.
Architecture Assessment
The 3-layer design is sound and extensible:
Layer 1: .gitignore / .gitnexusignore → ig.ignores() / ig.ignores(rel + '/')
Layer 2: DEFAULT_IGNORE_LIST → isHardcodedIgnoredDirectory()
Layer 3: shouldIgnorePath() → extensions, exact filenames
Each layer has a clear responsibility and can be modified independently. The IgnoreLike interface integration is stable across glob versions.
Future-proofing verdict:
| Dimension | Assessment |
|---|---|
Nested .gitignore support |
Requires interface change to createIgnoreFilter but architecture allows it — pass per-directory ig instances |
--no-gitignore CLI flag |
Clean add: just thread the boolean from CLI through walkRepositoryPaths to createIgnoreFilter |
| Watch mode / incremental index | G3 above is the only concern — minor |
| Cross-platform (Windows) | Works via path-scurry POSIX normalization, but implicit (G2) |
ignore package upgrades |
Stable API; ^7 semver range is safe |
The architecture is future-proof for the documented scope. The two paths most likely to be added (nested .gitignore, --no-gitignore CLI flag) are reachable without breaking changes.
Summary
| Priority | Gap | Blocking? |
|---|---|---|
| 🔴 | Clarify package-lock.json:38 review comment with @magyargergo |
Yes — open CHANGES_REQUESTED |
| 🟡 | Document GITNEXUS_NO_GITIGNORE in CLI help / README |
Recommended |
| 🟢 | Add integration test for GITNEXUS_NO_GITIGNORE + walkRepositoryPaths |
Nice-to-have |
| 🟢 | Add path normalization comment or guard in ignored()/childrenIgnored() |
Nice-to-have |
The implementation is solid and correctly addresses the core problem. The only blocker is the unresolved package-lock.json review comment — once that's clarified, this PR is ready to merge from a code quality standpoint.
|
Out out curiousity: why are you using force-push? |
My preference is to keep PR history clean and transparent — 2 focused commits instead of a merge commit pulling in 150 unrelated upstream changes. This makes the diff reviewable and the intent of each commit clear. That said, if the project prefers merge-based workflows over rebase, I'm happy to adjust for future contributions. Let me know! |
- G1: Document GITNEXUS_NO_GITIGNORE in `analyze --help` and log when active - G2: Add comment clarifying path-scurry POSIX normalization contract - G3: Add IgnoreOptions interface — env var now falls back, callers can pass `noGitignore` explicitly for testability and future CLI flag - G4: Add integration test verifying walkRepositoryPaths respects the env var Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
I think these PRs should be coordinated. They overlap on
My preference would be to use #231 as the base for ignore handling, then extract or fold in the unsupported-language skipping logic from #301, rather than merging two separate ignore implementations. That would let us:
So from my point of view, these are better treated as complementary pieces that should be consolidated. |
|
@magyargergo Agreed — consolidation is the right call. Here's how I see the two PRs fitting together: Where #231 is strongerAutomatic Directory-level pruning via Escape hatch. Test coverage. #231 has 25 unit + 8 integration tests across What #301 adds that #231 doesn'tUnsupported language resilience. Kotlin optional import fix. Skip logging. Tracks and reports skipped unsupported languages with file counts (e.g., Wiki generator coverage. Moved Proposed consolidation path
@ivkond happy to coordinate on timing. If #231 merges first, I can rebase #301 within a day to cleanly layer the language resilience on top. |
|
One more thing I would like to ask befor I merge this, is to add some e2e test coverage with a small fixture example test set to have this tested end-to-end. Plus you'll need to update the GitHub worlflow to include that new test. Thank you! |
…rammars Port unsupported language resilience from PR #301 by @jecanore. - Make Kotlin import optional (like Swift) in parser-loader and parse-worker - Add worker-local isLanguageAvailable() with filePath param for tsx distinction - Track and log skipped files per language in both sequential and worker paths - Add skippedLanguages to ParseWorkerResult for worker→main aggregation - Add isLanguageAvailable unit tests Refs: #301, #155, #228 Co-Authored-By: jecanore <juan@housingbase.io> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidated with PR #301 (unsupported language resilience)Per @magyargergo's request, this commit ports the language-skip logic from PR #301 by @jecanore into this branch. Ported from PR #301
Not portedPR #301's ignore-service changes — our implementation is more complete ( AttributionCommit includes This PR now addresses both #228 and #155 in a single branch. |
Thanks for the feedback! To clarify the scope, do you mean:
I want to make sure the fixture scope and workflow placement match your expectations before implementing. |
Yes please!
Already existing test job in
This is a bit of mess but hoping for automatic discovery after my PR gets merged in LadybugDB/ladybug-nodejs#1. |
@jecanore arre you happy with this approach? This is not what I had in mind honestly but works either ways. |
Add a fixture repo (test/fixtures/ignore-and-skip-repo/) with .gitignore, .gitnexusignore, TypeScript source files, and a Swift file to exercise all three features end-to-end: - File discovery: verifies .gitignore excludes data/ and *.log, .gitnexusignore excludes vendor/, source files are discovered - Parsing: verifies TypeScript files produce Function nodes and DEFINES relationships, Swift files are skipped gracefully when grammar is unavailable Add the test to the standalone group in ci-integration.yml and coverage job. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clarify that the filePath parameter handles .tsx distinction at the worker level, while the main-thread version does this inside loadLanguage() instead. Rebased on top of abhigyanpatwari#231 — all ignore and language resilience changes from abhigyanpatwari#301 were already ported by ivkond in 505fc9b. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The fixture's .gitignore prevented data/seed.json and debug.log from being committed — these files would be missing after checkout in CI. Switch to creating the entire test structure in a temp directory via beforeAll (matching filesystem-walker.test.ts pattern). This ensures all files exist regardless of git ignore rules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use graph.nodes property getter instead of graph.getNodes(), and check Function node filePath instead of non-existent File nodes (File nodes are created by processStructure, not processParsing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
This is unreleated but can you please add the |
|
@magyargergo, shure, omw. |
|
@magyargergo, just to clarify — |
This one please 🙏 |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Apologies, could we move this up to the |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s perm Three issues prevented Claude from running on fork PRs: 1. claude-code-review.yml lacked workflows:write — push failed when fork PRs modify .github/workflows/ files 2. claude.yml had no fork PR support — checked out main and couldn't fetch the fork's branch from origin 3. Cleanup step unconditionally deleted branches even when push failed, breaking the concurrent claude.yml workflow Also removes workflows:write from ci.yml's integration job — CI tests don't need that permission. The permission belongs on the claude workflows that push fork branches. Changes: - Add workflows:write to both claude workflow permissions blocks - Add fork PR detection + branch push/cleanup to claude.yml - Add step id to push-fork; cleanup only runs if push succeeded - Pass branch names via env vars to prevent shell injection (security) - Add concurrency groups to prevent race conditions between workflows - Remove misplaced workflows:write from ci.yml integration job
GITHUB_TOKEN cannot have 'workflows' permission — it's only valid for PATs and GitHub Apps. This means git push fails whenever a fork PR modifies .github/workflows/ files. Replace git push with the GitHub REST API (POST/PATCH /git/refs) to create temporary branch refs. The API creates a pointer to the already-existing PR head commit without triggering the workflow file push protection. Similarly, cleanup uses DELETE /git/refs instead of git push --delete. Also removes the invalid 'workflows: write' from permissions blocks.
|
Thank you for your contribution! |
…iscovery (abhigyanpatwari#231) * feat(ingestion): respect .gitignore and .gitnexusignore during file discovery Add support for excluding files from indexing based on .gitignore and .gitnexusignore patterns. Previously, GitNexus used only a hardcoded ignore list, causing significant index pollution in repositories with git-ignored directories containing code (e.g., Docker-mounted volumes). Changes: - Add `ignore` package for gitignore-spec pattern matching - Add `loadIgnoreRules()` to parse .gitignore + .gitnexusignore - Add `createIgnoreFilter()` returning glob-compatible IgnoreLike object - Integrate filter into glob's `ignore` option for directory-level pruning - Remove post-glob `.filter()` call (now handled during traversal) The hardcoded DEFAULT_IGNORE_LIST remains as fallback for non-git repos. Closes abhigyanpatwari#228 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ingestion): address review feedback on ignore filtering - Distinguish ENOENT vs EACCES in loadIgnoreRules (warn on permission errors) - Add GITNEXUS_NO_GITIGNORE env var to bypass .gitignore parsing - Fix bare-name pattern matching in childrenIgnored (check both with/without trailing slash) - Rename isIgnoredDirectory to isHardcodedIgnoredDirectory for clarity - Add clarifying comments for design decisions (D2 negation, D3 dot:false redundancy) - Add tests for bare-name patterns, file-glob patterns, EACCES handling, env var Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ingestion): address second round of review feedback - G1: Document GITNEXUS_NO_GITIGNORE in `analyze --help` and log when active - G2: Add comment clarifying path-scurry POSIX normalization contract - G3: Add IgnoreOptions interface — env var now falls back, callers can pass `noGitignore` explicitly for testability and future CLI flag - G4: Add integration test verifying walkRepositoryPaths respects the env var Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(ingestion): gracefully skip files with unavailable tree-sitter grammars Port unsupported language resilience from PR abhigyanpatwari#301 by @jecanore. - Make Kotlin import optional (like Swift) in parser-loader and parse-worker - Add worker-local isLanguageAvailable() with filePath param for tsx distinction - Track and log skipped files per language in both sequential and worker paths - Add skippedLanguages to ParseWorkerResult for worker→main aggregation - Add isLanguageAvailable unit tests Refs: abhigyanpatwari#301, abhigyanpatwari#155, abhigyanpatwari#228 Co-Authored-By: jecanore <juan@housingbase.io> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(e2e): add ignore + language-skip end-to-end test with fixture repo Add a fixture repo (test/fixtures/ignore-and-skip-repo/) with .gitignore, .gitnexusignore, TypeScript source files, and a Swift file to exercise all three features end-to-end: - File discovery: verifies .gitignore excludes data/ and *.log, .gitnexusignore excludes vendor/, source files are discovered - Parsing: verifies TypeScript files produce Function nodes and DEFINES relationships, Swift files are skipped gracefully when grammar is unavailable Add the test to the standalone group in ci-integration.yml and coverage job. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): move ignore-and-skip-e2e test to e2e group per review feedback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(test): use temp directory instead of fixture for e2e ignore test The fixture's .gitignore prevented data/seed.json and debug.log from being committed — these files would be missing after checkout in CI. Switch to creating the entire test structure in a temp directory via beforeAll (matching filesystem-walker.test.ts pattern). This ensures all files exist regardless of git ignore rules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(test): correct graph API usage in e2e ignore test Use graph.nodes property getter instead of graph.getNodes(), and check Function node filePath instead of non-existent File nodes (File nodes are created by processStructure, not processParsing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: add workflows permission to ci-integration.yml Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: change workflows permission to write per review Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: move workflows permission from ci-integration.yml to ci.yml caller Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): fix Claude workflows for fork PRs, remove misplaced workflows perm Three issues prevented Claude from running on fork PRs: 1. claude-code-review.yml lacked workflows:write — push failed when fork PRs modify .github/workflows/ files 2. claude.yml had no fork PR support — checked out main and couldn't fetch the fork's branch from origin 3. Cleanup step unconditionally deleted branches even when push failed, breaking the concurrent claude.yml workflow Also removes workflows:write from ci.yml's integration job — CI tests don't need that permission. The permission belongs on the claude workflows that push fork branches. Changes: - Add workflows:write to both claude workflow permissions blocks - Add fork PR detection + branch push/cleanup to claude.yml - Add step id to push-fork; cleanup only runs if push succeeded - Pass branch names via env vars to prevent shell injection (security) - Add concurrency groups to prevent race conditions between workflows - Remove misplaced workflows:write from ci.yml integration job * fix(ci): use GitHub API for fork branch refs instead of git push GITHUB_TOKEN cannot have 'workflows' permission — it's only valid for PATs and GitHub Apps. This means git push fails whenever a fork PR modifies .github/workflows/ files. Replace git push with the GitHub REST API (POST/PATCH /git/refs) to create temporary branch refs. The API creates a pointer to the already-existing PR head commit without triggering the workflow file push protection. Similarly, cleanup uses DELETE /git/refs instead of git push --delete. Also removes the invalid 'workflows: write' from permissions blocks. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: jecanore <juan@housingbase.io> Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>




Summary
.gitignore: files/dirs listed in the repo root.gitignoreare now excluded from indexing.gitnexusignore: custom ignore file (gitignore syntax) for project-specific exclusion patternschildrenIgnored, skipping entire subtrees (nostat()calls on ignored files)DEFAULT_IGNORE_LISTstill applies as fallbackMotivation
GitNexus currently indexes all files on the filesystem, filtering only through a hardcoded
DEFAULT_IGNORE_LIST. This causes significant noise in repos with git-ignored directories containing code.Real-world example: A repo with Docker-mounted Grafana plugins in
core/local/grafana/(listed in.gitignore) had ~1,950 symbols (~34% of index) from irrelevant plugin code. Top execution flows, clusters, and search results were all polluted.Changes
src/config/ignore-service.tsloadIgnoreRules(),createIgnoreFilter(),isIgnoredDirectory()src/core/ingestion/filesystem-walker.tscreateIgnoreFilter()in glob options, remove post-filterpackage.jsonignoredependency (^7.0.0, 11KB, 0 deps)test/unit/ignore-service.test.tsisIgnoredDirectory,loadIgnoreRules,createIgnoreFiltertest/integration/filesystem-walker.test.tsArchitecture
Three ignore layers combined into a single glob
IgnoreLikefilter:The
ignorenpm package (~30M weekly downloads, used by eslint) handles gitignore-spec parsing including negation patterns, comments, and glob matching.Scope limitations (documented for follow-up)
.gitignore— subdirectory.gitignorefiles are not loaded (covers 95%+ of real cases)--no-gitignoreCLI flag — can be added in a follow-upTest plan
loadIgnoreRuleswith .gitignore, .gitnexusignore, both, neitherisIgnoredDirectoryfor known and unknown dirscreateIgnoreFilterreturns valid IgnoreLike objectshouldIgnorePathunchanged behavior (all 86 existing tests pass).gitignoreexcludes directories from scan.gitnexusignoreexcludes directories from scantsccompiles without errorsCloses #228