Skip to content

Commit b8ee995

Browse files
committed
feat: implement note tagging system with parsing, filtering, and management features
1 parent 15dc265 commit b8ee995

File tree

6 files changed

+831
-0
lines changed

6 files changed

+831
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Spec Requirements Document
2+
3+
> Spec: Note Tagging System
4+
> Created: 2025-10-18
5+
> Status: Planning
6+
7+
## Overview
8+
9+
Implement a comprehensive tagging system for notes that allows users to organize and filter notes using hashtag-based tags in a metadata section. This feature will enhance note discoverability and organization beyond the current date-based folder structure.
10+
11+
## User Stories
12+
13+
### Organizing Notes with Tags
14+
15+
As a developer taking technical notes, I want to tag my notes with topics like #bug, #feature, #meeting, so that I can quickly find all notes related to a specific topic regardless of when they were created.
16+
17+
**Workflow**: User creates or opens a note, adds a tags metadata section at the top (e.g., `tags: #project-alpha #bug #urgent`), saves the note. The extension parses the tags and makes them available for filtering and search. User can then filter the tree view to show only notes with specific tags, or search for notes by tag.
18+
19+
### Discovering Related Content
20+
21+
As a note-taker, I want to see all available tags with usage counts, so that I can understand how I've organized my notes and discover patterns in my note-taking.
22+
23+
**Workflow**: User opens the Tags section in the tree view, which displays all tags sorted by frequency or alphabetically. Clicking a tag filters the notes tree to show only notes containing that tag. User can also use the command palette to search/filter by tags.
24+
25+
### Managing Tag Taxonomy
26+
27+
As a long-term user, I want to rename or merge tags across all notes, so that I can maintain a clean and consistent tagging system as my needs evolve.
28+
29+
**Workflow**: User right-clicks a tag in the Tags section and selects "Rename Tag" or "Merge Tag". The extension updates all notes containing the old tag with the new tag name, maintaining note integrity.
30+
31+
## Spec Scope
32+
33+
1. **Tag Parsing and Metadata** - Parse hash-based tags (`#tag-name`) from a dedicated metadata section at the top of notes
34+
2. **Tags Tree View Section** - New collapsible "Tags" section in the sidebar showing all tags with usage counts
35+
3. **Tag Filtering** - Filter notes tree view by single or multiple tags via tree view UI and command palette
36+
4. **Enhanced Search** - Integrate tag-based search with existing full-text search using `tag:name` syntax
37+
5. **Tag Management Commands** - Commands for viewing all tags, renaming tags, merging tags, and deleting unused tags
38+
6. **Tag Autocomplete** - Suggest existing tags when typing in the metadata section
39+
40+
## Out of Scope
41+
42+
- Inline tags within note content (only metadata section supported in v1)
43+
- Tag hierarchies or nested tags (e.g., `#project/alpha`)
44+
- Tag colors or visual customization
45+
- Tag aliases or synonyms
46+
- Automatic tag suggestions based on note content (AI-powered)
47+
- Tag-based note templates
48+
49+
## Expected Deliverable
50+
51+
1. Users can add tags to notes in a metadata section and see them parsed correctly
52+
2. Tags section appears in the tree view with all available tags and counts
53+
3. Clicking a tag filters the notes tree to show only tagged notes
54+
4. Search command supports `tag:name` syntax combined with text search
55+
5. Tag management commands (rename, merge, delete) work correctly across all notes
56+
6. Tag autocomplete suggests existing tags when typing `#` in metadata section
57+
58+
## Spec Documentation
59+
60+
- Tasks: @.agent-os/specs/2025-10-18-note-tagging-system/tasks.md
61+
- Technical Specification: @.agent-os/specs/2025-10-18-note-tagging-system/sub-specs/technical-spec.md
62+
- Tests Specification: @.agent-os/specs/2025-10-18-note-tagging-system/sub-specs/tests.md
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Technical Specification
2+
3+
This is the technical specification for the spec detailed in @.agent-os/specs/2025-10-18-note-tagging-system/spec.md
4+
5+
> Created: 2025-10-18
6+
> Version: 1.0.0
7+
8+
## Technical Requirements
9+
10+
### Tag Parsing and Storage
11+
12+
- **Metadata Format**: Tags appear at the top of notes in format: `tags: #tag1 #tag2 #tag3`
13+
- **Tag Pattern**: Hash-based (`#`), followed by lowercase alphanumeric with hyphens: `/\#[a-z0-9-]+/g`
14+
- **Case Handling**: Tags are case-insensitive (convert to lowercase for storage/comparison)
15+
- **Tag Extraction**: Parse metadata section (first 10 lines) to extract tags using regex
16+
- **Caching Strategy**: Cache tag index in memory, rebuild on file changes or command trigger
17+
18+
### UI Components
19+
20+
- **Tags Tree Provider**: New `TagsTreeProvider` class implementing `vscode.TreeDataProvider<TagItem>`
21+
- **Tag Items**: `TagItem` class with properties: `tagName`, `count`, `noteReferences[]`
22+
- **Tree View Integration**: Add "Tags" section to existing `notedView` container
23+
- **Collapsible State**: Tags section starts expanded, maintains state across sessions
24+
- **Context Menus**: Right-click context menu on tag items for rename/merge/delete operations
25+
26+
### Filtering Logic
27+
28+
- **Active Filter State**: Store active tag filters in `NotesTreeProvider` state
29+
- **Filter Indicator**: Show active filters in tree view title/description
30+
- **Multi-Tag Filtering**: Support AND logic (show notes with ALL selected tags)
31+
- **Clear Filters**: Command and UI button to clear all active tag filters
32+
- **Performance**: Filter tree items in-memory, no file re-reading required
33+
34+
### Search Integration
35+
36+
- **Search Syntax**: Support `tag:tagname` in search input
37+
- **Combined Search**: Allow `tag:bug error message` to search tags + text
38+
- **Multiple Tags**: Support `tag:bug tag:urgent` for multi-tag search
39+
- **Search Results**: Highlight matched tags in search results preview
40+
41+
### Tag Management Operations
42+
43+
- **Rename Tag**: Find all notes with tag, update metadata section, preserve formatting
44+
- **Merge Tags**: Combine two tags into one across all notes, remove duplicates
45+
- **Delete Tag**: Remove tag from all notes, confirm before deletion
46+
- **List Tags**: Export all tags with counts to JSON or display in output panel
47+
- **Atomic Updates**: Use async file operations with error rollback
48+
49+
### Autocomplete Provider
50+
51+
- **Trigger Character**: `#` in metadata section
52+
- **Completion Items**: Return existing tags sorted by frequency
53+
- **Context Awareness**: Only trigger in first 10 lines (metadata section)
54+
- **VSCode API**: Implement `vscode.CompletionItemProvider` interface
55+
56+
## Approach Options
57+
58+
### Option A: Real-time Tag Parsing (Selected)
59+
- **Description**: Parse tags on-demand when notes are opened/modified
60+
- **Pros**: Always up-to-date, no stale data, simpler implementation
61+
- **Cons**: Slower for large note collections, repeated parsing
62+
- **Rationale**: Better for MVP, can optimize later with caching layer
63+
64+
### Option B: Persistent Tag Index
65+
- **Description**: Build and persist tag index to workspace state
66+
- **Pros**: Faster performance, one-time parsing cost
67+
- **Cons**: More complex, requires sync logic, potential stale data
68+
- **Rationale**: Consider for v2 if performance issues arise
69+
70+
## External Dependencies
71+
72+
**None required** - Implementation uses only existing VS Code API and Node.js built-ins:
73+
- `vscode.TreeDataProvider` for tree views
74+
- `vscode.CompletionItemProvider` for autocomplete
75+
- `fs.promises` for file operations (already in use)
76+
- Native JavaScript regex for tag parsing
77+
78+
## Performance Considerations
79+
80+
- **Tag Index Rebuild**: < 500ms for 1000 notes (async operation)
81+
- **Filter Operation**: < 100ms for filtering tree with 1000 notes
82+
- **Search with Tags**: < 1s for searching 1000 notes with tag + text query
83+
- **Autocomplete**: < 50ms to generate completion list
84+
85+
## File Structure
86+
87+
New files to create:
88+
```
89+
src/
90+
providers/
91+
tagsTreeProvider.ts (~200 lines) - Tags tree view provider
92+
services/
93+
tagService.ts (~300 lines) - Tag parsing, indexing, management
94+
commands/
95+
tagCommands.ts (~250 lines) - Tag-related command handlers
96+
utils/
97+
tagHelpers.ts (~100 lines) - Tag validation, formatting utilities
98+
```
99+
100+
Modifications to existing files:
101+
```
102+
src/extension.ts - Register tag commands and tree provider
103+
src/providers/notesTreeProvider.ts - Add filter state and logic
104+
src/services/noteService.ts - Integrate tag search in searchNotes()
105+
package.json - Add new commands, tree view, configuration
106+
```
107+
108+
## Configuration Settings
109+
110+
Add to `package.json` contributions:
111+
```json
112+
{
113+
"noted.enableTags": {
114+
"type": "boolean",
115+
"default": true,
116+
"description": "Enable tag system for notes"
117+
},
118+
"noted.tagAutoComplete": {
119+
"type": "boolean",
120+
"default": true,
121+
"description": "Enable tag autocomplete suggestions"
122+
},
123+
"noted.tagSortOrder": {
124+
"type": "string",
125+
"enum": ["frequency", "alphabetical"],
126+
"default": "frequency",
127+
"description": "Sort order for tags in tree view"
128+
}
129+
}
130+
```
131+
132+
## VS Code Commands
133+
134+
New commands to register:
135+
- `noted.filterByTag` - Show quick pick to select tags for filtering
136+
- `noted.clearTagFilters` - Clear all active tag filters
137+
- `noted.renameTag` - Rename a tag across all notes
138+
- `noted.mergeTags` - Merge two tags into one
139+
- `noted.deleteTag` - Remove tag from all notes
140+
- `noted.exportTags` - Export tag index to JSON
141+
- `noted.refreshTags` - Manually rebuild tag index
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# Tests Specification
2+
3+
This is the tests coverage details for the spec detailed in @.agent-os/specs/2025-10-18-note-tagging-system/spec.md
4+
5+
> Created: 2025-10-18
6+
> Version: 1.0.0
7+
8+
## Test Coverage
9+
10+
### Unit Tests
11+
12+
**tagHelpers.ts**
13+
- `extractTagsFromContent()` extracts tags from metadata section
14+
- `extractTagsFromContent()` ignores tags in note body beyond metadata
15+
- `extractTagsFromContent()` handles empty content
16+
- `extractTagsFromContent()` handles content without tags
17+
- `extractTagsFromContent()` converts tags to lowercase
18+
- `extractTagsFromContent()` handles duplicate tags (returns unique set)
19+
- `isValidTag()` validates tag format (alphanumeric + hyphens)
20+
- `isValidTag()` rejects tags with spaces
21+
- `isValidTag()` rejects tags with special characters
22+
- `formatTagForDisplay()` formats tag with hash prefix
23+
- `formatTagForStorage()` normalizes tag to lowercase
24+
25+
**tagService.ts**
26+
- `buildTagIndex()` scans all notes and builds tag index
27+
- `buildTagIndex()` handles notes without tags
28+
- `buildTagIndex()` counts tag occurrences correctly
29+
- `buildTagIndex()` stores note file paths for each tag
30+
- `getTagsForNote()` returns tags for a specific note
31+
- `getNotesWithTag()` returns all notes containing a tag
32+
- `getNotesWithTags()` returns notes with all specified tags (AND logic)
33+
- `getAllTags()` returns sorted tag list
34+
- `renameTag()` updates tag in all notes
35+
- `renameTag()` handles file write errors gracefully
36+
- `mergeTags()` combines tags and removes duplicates
37+
- `deleteTag()` removes tag from all notes
38+
- `addTagToNote()` adds tag to metadata section
39+
- `addTagToNote()` creates metadata section if missing
40+
- `removeTagFromNote()` removes tag from metadata section
41+
42+
**tagsTreeProvider.ts**
43+
- `getChildren()` returns all tags as TagItems
44+
- `getChildren()` returns empty array when no tags exist
45+
- `getTreeItem()` creates tree item with correct label and count
46+
- `refresh()` triggers tree update
47+
- `sortTags()` sorts by frequency when configured
48+
- `sortTags()` sorts alphabetically when configured
49+
50+
### Integration Tests
51+
52+
**Tag Filtering Workflow**
53+
- User can filter notes by single tag via tree view click
54+
- User can filter notes by multiple tags via command palette
55+
- Filtered tree view shows only notes with selected tags
56+
- Clear filters command restores full tree view
57+
- Filter state persists during session
58+
- Filter indicator shows active tags in tree view title
59+
60+
**Tag Management Workflow**
61+
- Rename tag command updates all notes successfully
62+
- Rename tag command shows confirmation with affected note count
63+
- Merge tags command combines tags and removes duplicates
64+
- Delete tag command removes tag from all notes after confirmation
65+
- Tag operations handle file system errors gracefully
66+
- Tag operations refresh tree view automatically
67+
68+
**Search Integration Workflow**
69+
- Search with `tag:name` returns only notes with tag
70+
- Search with `tag:bug tag:urgent` returns notes with both tags
71+
- Search with `tag:bug error` returns notes with tag containing "error"
72+
- Search results highlight matched tags
73+
- Search handles malformed tag syntax gracefully
74+
75+
**Autocomplete Workflow**
76+
- Typing `#` in metadata section triggers autocomplete
77+
- Autocomplete shows existing tags sorted by frequency
78+
- Selecting autocomplete inserts tag correctly
79+
- Autocomplete only triggers in first 10 lines
80+
- Autocomplete handles empty tag list
81+
82+
### Performance Tests
83+
84+
**Tag Index Building**
85+
- Build tag index for 100 notes completes in < 200ms
86+
- Build tag index for 1000 notes completes in < 500ms
87+
- Incremental index update for single note < 50ms
88+
89+
**Filtering Performance**
90+
- Filter 100 notes by single tag < 50ms
91+
- Filter 1000 notes by single tag < 100ms
92+
- Filter by multiple tags scales linearly
93+
94+
**Search Performance**
95+
- Search with tag + text in 100 notes < 200ms
96+
- Search with tag + text in 1000 notes < 1s
97+
98+
### Edge Cases and Error Handling
99+
100+
**Malformed Metadata**
101+
- Handle notes with malformed metadata gracefully
102+
- Handle notes with tags outside metadata section
103+
- Handle notes with invalid tag characters
104+
- Handle notes with extremely long tag lists (>100 tags)
105+
106+
**File System Errors**
107+
- Handle read errors during tag index building
108+
- Handle write errors during tag rename/merge/delete
109+
- Provide user-friendly error messages
110+
- Roll back failed operations where possible
111+
112+
**Concurrent Operations**
113+
- Handle multiple tag operations in quick succession
114+
- Handle tag index rebuild during active filtering
115+
- Handle external file modifications during tag operations
116+
117+
## Mocking Requirements
118+
119+
**VS Code API Mocks**
120+
- `vscode.workspace.workspaceFolders` for workspace path
121+
- `vscode.window.showQuickPick` for tag selection UI
122+
- `vscode.window.showInputBox` for rename tag input
123+
- `vscode.window.showInformationMessage` for confirmations
124+
- `vscode.window.showErrorMessage` for error display
125+
- `vscode.TreeDataProvider` event emitters
126+
127+
**File System Mocks**
128+
- Mock `fs.promises.readFile` for reading note files
129+
- Mock `fs.promises.writeFile` for updating notes
130+
- Mock `fs.promises.readdir` for scanning note directories
131+
- Mock file system errors for error handling tests
132+
133+
**Configuration Mocks**
134+
- Mock `vscode.workspace.getConfiguration` for settings
135+
- Mock different tag sort order settings
136+
- Mock enable/disable tag features
137+
138+
## Test Data
139+
140+
**Sample Notes with Tags**
141+
```
142+
File: 2025-10-15.txt
143+
Content:
144+
tags: #bug #urgent #project-alpha
145+
146+
Found critical bug in user authentication.
147+
Need to fix ASAP.
148+
```
149+
150+
```
151+
File: 2025-10-16.txt
152+
Content:
153+
tags: #feature #project-alpha
154+
155+
Implementing new dashboard feature.
156+
```
157+
158+
```
159+
File: 2025-10-17.txt
160+
Content:
161+
No tags
162+
163+
Just some quick notes without tags.
164+
```
165+
166+
**Expected Tag Index**
167+
```javascript
168+
{
169+
"bug": { count: 1, notes: ["2025-10-15.txt"] },
170+
"urgent": { count: 1, notes: ["2025-10-15.txt"] },
171+
"project-alpha": { count: 2, notes: ["2025-10-15.txt", "2025-10-16.txt"] },
172+
"feature": { count: 1, notes: ["2025-10-16.txt"] }
173+
}
174+
```
175+
176+
## Coverage Goals
177+
178+
- **Unit Tests**: ≥ 90% coverage for tag utilities and services
179+
- **Integration Tests**: All major user workflows covered
180+
- **Edge Cases**: All error scenarios have dedicated tests
181+
- **Performance**: All performance benchmarks validated

0 commit comments

Comments
 (0)