- Added test for getFolderWaypoint file read error handling (line 777)
- Documented unreachable defensive code in stat() (lines 452-456)
- Documented unreachable defensive code in exists() (lines 524-528)
- Added istanbul ignore comments for unreachable defensive returns
Analysis:
- Lines 452-456 and 524-528 are unreachable because getAbstractFileByPath
only returns TFile, TFolder, or null - all cases are handled before
the defensive fallback code
- Line 777 is now covered by testing file read errors in getFolderWaypoint
Coverage: vault-tools.ts now at 100% statement coverage (99.8% tools overall)
Test count: 84 vault-tools tests, 505 total tests passing
- Add test for list() skipping root folder (line 267)
- Add test for list() normalizing aliases from string to array (line 325)
- Add test for list() handling array aliases (line 325)
- Add test for getFolderMetadata() handling folder with mtime (line 374)
- Add test for getFolderMetadata() handling folder without mtime
- Add test for list() on non-root path (line 200)
- Add test for search() stopping at maxResults=1 on file boundary (line 608)
- Add test for search() stopping at maxResults=1 within file (line 620)
- Add test for search() adjusting snippet for long lines (line 650)
Coverage improved from 95.66% to 98.19% for vault-tools.ts
Added targeted test cases to improve vault-tools.ts coverage:
- Test for listNotes() with invalid vault path (covers line 76)
- Test for list() with glob excludes filtering (covers line 272)
- Test for search() with glob include/exclude patterns (covers lines 596-597)
Coverage improved from 94.22% to 95.66% for vault-tools.ts.
All tests passing (75 tests).
Add test for read_excalidraw with includeCompressed option to cover
line 647. Add test for update_frontmatter on files without existing
frontmatter to cover line 771.
Coverage for note-tools.ts now at 100% line coverage (99.6% statement,
92.82% branch, 90.9% function).
Add 5 tests for folder-not-file error cases:
- read_note when path is a folder (line 61-66 in source)
- rename_file when source path is a folder (line 377)
- rename_file when destination path is a folder (line 408)
- read_excalidraw when path is a folder (line 590)
- update_frontmatter when path is a folder (line 710)
- update_sections when path is a folder (line 836)
All tests verify error message uses ErrorMessages.notAFile()
Coverage for note-tools.ts increased to 98%
Add test case for conflict resolution loop in createNote when multiple
numbered file variants exist. Test verifies the loop correctly increments
counter (lines 238-239) by creating file 3.md when file.md, file 1.md,
and file 2.md already exist.
Coverage improvement: note-tools.ts 96.01% -> 96.81%
Lines 238-239 now covered.
- Add 46 comprehensive tests for LinkUtils covering all methods
- Test parseWikilinks() with various formats, aliases, headings, paths
- Test resolveLink() with MetadataCache integration and edge cases
- Test findSuggestions() with scoring algorithms and fuzzy matching
- Test getBacklinks() with linked/unlinked mentions and snippet extraction
- Test validateWikilinks() with resolved/unresolved link validation
- Achieve 100% statement, function, and line coverage on link-utils.ts
- Test extractWaypointBlock() with valid/invalid waypoints, unclosed blocks, multiple links
- Test hasWaypointMarker() with all marker combinations
- Test isFolderNote() with basename match, waypoint marker, both, neither, file read errors
- Test wouldAffectWaypoint() detecting removal, content changes, acceptable moves
- Test getParentFolderPath() and getBasename() helper methods
- Achieve 100% coverage on waypoint-utils.ts (52 tests)
Updated VaultTools to use adapters for all utility method calls:
- SearchUtils.searchWaypoints() now receives vault adapter
- WaypointUtils.isFolderNote() now receives vault adapter
- LinkUtils.validateWikilinks() now receives vault and metadata adapters
- LinkUtils.resolveLink() now receives vault and metadata adapters
- LinkUtils.getBacklinks() now receives vault and metadata adapters
Removed App dependency from VaultTools constructor - now only requires
vault and metadata adapters. Updated factory and all test files accordingly.
All tests passing (336/336).
- Change WaypointUtils.isFolderNote() signature to accept IVaultAdapter
instead of App
- Update method body to use vault.read() instead of app.vault.read()
- Callers will be updated in next commit
- Test all glob pattern types: *, **, ?, [abc], {a,b}
- Test edge cases: unclosed brackets, unclosed braces
- Test all public methods: matches(), matchesIncludes(), matchesExcludes(), shouldInclude()
- Test special regex character escaping: . / ( ) + ^ $ | \
- Test complex pattern combinations and real-world scenarios
- Achieve 100% coverage on glob-utils.ts (52 tests)
Summary of dependency injection refactoring:
- 96% coverage on NoteTools
- 94% coverage on VaultTools
- 236 tests passing
- Adapter pattern fully implemented
- Factory functions for production usage
Architecture improvements:
- IVaultAdapter, IMetadataCacheAdapter, IFileManagerAdapter interfaces
- Clean separation between business logic and Obsidian API
- Simplified test mocking with adapter pattern
- Type-safe dependency injection throughout
Update parent-folder-detection.test.ts to use the new mock adapter
pattern (createMockVaultAdapter, createMockFileManagerAdapter) instead
of manually mocking Obsidian API objects.
Key changes:
- Replace manual vault/app mocks with adapter helpers
- Use createMockTFile and createMockTFolder for consistent fixtures
- Fix mock reference synchronization with getter pattern for App.vault
- Standardize all mock reassignments to use jest.fn() methods
- Update all 14 tests to properly reassign mocks in test setup
This resolves all 7 failing tests and improves test maintainability
by using consistent mock patterns across the test suite.
All tests passing: 14/14 in parent-folder-detection.test.ts
Implements Task 10 from the implementation plan:
1. Updated NoteTools constructor to accept IVaultAdapter and IFileManagerAdapter
2. Created note-tools-factory.ts with factory function
3. Migrated all CRUD methods to use adapters:
- readNote: uses vault.read()
- createNote: uses vault.create(), vault.delete()
- createParentFolders: uses vault.createFolder()
- updateNote: uses vault.read(), vault.modify()
- deleteNote: uses vault.trash(), vault.delete()
- renameFile: uses fileManager.renameFile()
- readExcalidraw: uses vault.read()
- updateFrontmatter: uses vault.read(), vault.modify()
- updateSections: uses vault.read(), vault.modify()
4. Extended IVaultAdapter interface with modify(), delete(), and trash() methods
5. Implemented new methods in VaultAdapter
6. Updated ToolRegistry to use factory function
7. Kept app parameter temporarily for PathUtils dependency
8. All methods now use adapters instead of direct Obsidian API calls
9. Code compiles successfully
This change enables 100% test coverage by allowing full mocking of vault operations.
Update validateWikilinks, resolveWikilink, and getBacklinks methods
to use IVaultAdapter and IMetadataCacheAdapter instead of direct App access.
- Implemented inline link suggestion finding using vault adapter
- Implemented backlinks retrieval using metadata cache adapter
- Added helper methods: findLinkSuggestions, extractSnippet, escapeRegex
- App parameter still required for waypoint methods (not in scope for this task)
Update search and getVaultInfo methods to use IVaultAdapter
instead of direct App.vault access. Implements inline search
logic using adapters for file reading and markdown file listing.
Use createMockTFolder helper which includes isRoot() method.
Replace old App mocks with createMockVaultAdapter pattern.
Properly mock getRoot() method to return root folder with children.
Fixes TypeError: item.isRoot is not a function.
Replace complex App object mocks with clean mock adapter pattern.
Simplifies test setup and improves maintainability.
- Created comprehensive tests for VaultTools methods using mock adapters
- Tests cover listNotes, stat, exists, and list (enhanced) functionality
- Includes tests for frontmatter extraction edge cases
- Fixed mock helpers to use proper prototype chains for instanceof checks
- All 27 VaultTools tests passing
Update VaultTools constructor to accept IVaultAdapter and
IMetadataCacheAdapter. Add factory function for production usage.
Update stat, exists, and createFileMetadataWithFrontmatter methods.
Add comprehensive design for achieving 100% test coverage through
dependency injection refactoring. The design introduces adapter
interfaces to decouple tool classes from Obsidian API dependencies,
enabling cleaner, more maintainable tests.
Key elements:
- IVaultAdapter, IMetadataCacheAdapter, IFileManagerAdapter interfaces
- Factory pattern for production usage
- Phased implementation approach (adapters → VaultTools → NoteTools → integration)
- Mock adapter pattern for simplified test setup
- Coverage strategy organized by feature areas
Goal: Codebase confidence for future refactoring and feature work.
Implement visual feedback for MCP tool calls with configurable notifications.
Features:
- Real-time notifications when tools are called (request only, no completion)
- Tool-specific emoji icons for visual clarity
- Rate limiting (max 10 notifications/second)
- Notification history tracking (last 100 entries)
- Configurable settings: enable/disable, show parameters, duration, console logging
- History modal with filtering and export to clipboard
Implementation:
- Created NotificationManager with queue-based rate limiting
- Created NotificationHistoryModal for viewing past tool calls
- Integrated into tool call interceptor in ToolRegistry
- Added notification settings UI section
- Added 'View MCP Notification History' command
Benefits:
- Visual feedback for debugging and monitoring
- Transparency into AI agent actions
- Simple on/off toggle, no complex verbosity settings
- Zero performance impact when disabled
- History tracks success/failure/duration for all calls
All 10 phases of the roadmap are now complete\!
Implement three new tools for wikilink validation, resolution, and backlink queries:
New Tools:
- validate_wikilinks: Validate all wikilinks in a note with suggestions for broken links
- resolve_wikilink: Resolve a single wikilink to its target path
- backlinks: Get all backlinks to a note with optional unlinked mentions
New Files:
- src/utils/link-utils.ts: Complete wikilink parsing, resolution, and backlink utilities
Modified Files:
- src/tools/vault-tools.ts: Added 3 new methods for link operations
- src/tools/index.ts: Added 3 tool definitions and handlers
- src/types/mcp-types.ts: Added Phase 9 type definitions
- ROADMAP.md: Marked Phase 9 as complete
- CHANGELOG.md: Added v8.0.0 release notes
Key Features:
- Regex-based wikilink parsing with position tracking
- Uses MetadataCache.getFirstLinkpathDest() for accurate resolution
- Fuzzy matching suggestion engine for broken links
- Efficient backlink detection using MetadataCache.resolvedLinks
- Optional unlinked mentions with word-boundary matching
- Context snippet extraction for each occurrence
- Add get_folder_waypoint tool to extract waypoint blocks from folder notes
- Add is_folder_note tool to detect folder notes by basename or waypoint markers
- Implement waypoint edit protection in update_note to prevent corruption
- Create waypoint-utils.ts with helper functions for waypoint operations
- Add FolderWaypointResult and FolderNoteResult types
- Update ROADMAP.md and CHANGELOG.md with Phase 7 completion
- All manual tests passing
- Add enhanced 'search' tool with regex support, case sensitivity control, and advanced filtering
- Add 'search_waypoints' tool for finding Waypoint plugin markers
- Implement SearchUtils with regex/literal search, snippet extraction, and match highlighting
- Add WaypointResult and WaypointSearchResult types
- Update SearchResult type to include isRegex field
- Remove deprecated search_notes tool (breaking change)
- Support glob filtering (includes/excludes) and folder scoping
- Configurable snippet length and result limiting
- Extract wikilinks from waypoint content
Breaking Changes:
- search_notes tool removed, use 'search' tool instead
- Enhanced read_note tool with frontmatter parsing options
- parseFrontmatter option to separate frontmatter from content
- withFrontmatter and withContent options for flexible responses
- Returns structured ParsedNote JSON when parsing enabled
- Backward compatible (default behavior unchanged)
- New read_excalidraw tool for Excalidraw file metadata
- Detects compressed-json format (Excalidraw's actual format)
- Returns elementCount, hasCompressedData, metadata fields
- Handles compressed (base64) and uncompressed formats
- Preview text extraction from Text Elements section
- Optional full compressed data inclusion
- New frontmatter-utils.ts for YAML parsing
- Uses Obsidian's built-in parseYaml
- Extracts and parses frontmatter
- Handles edge cases (no frontmatter, malformed YAML)
- Excalidraw metadata parsing with compression detection
- Enhanced type definitions with JSDoc comments
- ParsedNote interface for structured note data
- ExcalidrawMetadata interface with detailed field docs
- Clear documentation of all fields and their purposes
- Comprehensive documentation
- IMPLEMENTATION_NOTES_PHASE5.md - Implementation details
- EXCALIDRAW_FIX_SUMMARY.md - Bug fix documentation
- EXCALIDRAW_TESTING_GUIDE.md - Testing instructions
- Updated CHANGELOG.md with all changes
- Updated ROADMAP.md marking Phase 5 complete
- Known limitation documented
- elementCount returns 0 for compressed files (expected)
- Decompression would require pako library (not included)
- hasCompressedData correctly identifies compressed files
- Preview text still available without decompression
- Added to roadmap as future enhancement
All manual tests passed. Phase 5 complete and production-ready.
- Add stat tool for detailed file/folder metadata
- Add exists tool for fast path existence checking
- Add StatResult and ExistsResult type definitions
- Implement stat() and exists() methods in VaultTools
- Register both tools in ToolRegistry with complete schemas
- Update version to 2.1.0
- Update ROADMAP.md to mark Phase 3 complete
- Update CHANGELOG.md with Phase 3 release notes
- Add IMPLEMENTATION_NOTES_PHASE3.md documentation
- Clean up old phase documentation files
Phase 2 - Breaking Changes (v2.0.0):
- Added typed result interfaces (FileMetadata, DirectoryMetadata, VaultInfo, SearchResult, SearchMatch)
- Unified parameter naming: list_notes now uses 'path' parameter (removed 'folder')
- Enhanced tool responses with structured JSON for all tools
- list_notes: Returns array of FileMetadata/DirectoryMetadata with full metadata
- search_notes: Returns SearchResult with line numbers, snippets, and match ranges
- get_vault_info: Returns VaultInfo with comprehensive statistics
- Updated all tool descriptions to document structured responses
- Version bumped to 2.0.0 (breaking changes)
Phase 2.1 - Post-Testing Fixes:
- Fixed root listing to exclude vault root folder itself (handles path '', '/', and isRoot())
- Fixed alphabetical sorting to be case-insensitive for stable ordering
- Improved directory metadata with better timestamp detection and error handling
- Fixed parent folder validation order (check if file before checking existence)
- Updated documentation with root path examples and leading slash warnings
- Added comprehensive test suite for sorting and root listing behavior
- Fixed test mocks to use proper TFile/TFolder instances
Tests: All 64 tests passing
Build: Successful, no errors