feat: support opening notes by title in bear-open-note#84
feat: support opening notes by title in bear-open-note#84
Conversation
Add title parameter as an alternative to id for direct note lookup. Case-insensitive matching with disambiguation when multiple notes share the same title. Created with Claude Code under the supervision of Serhii Vasylenko
- Return soft error via createToolResponse() instead of throwing when neither id nor title is provided (Pattern B consistency) - Use COLLATE NOCASE instead of LOWER() for idiomatic SQLite case folding - Improve not-found message to mention partial text match via bear-search-notes - Add missing test cases: no-args validation and open-by-ID regression Created with Claude Code under the supervision of Serhii Vasylenko
Ensure note ID is extracted successfully before proceeding to the actual test step, consistent with the regression test case that already had this guard. Created with Claude Code under the supervision of Serhii Vasylenko
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
Adds direct title-based lookup to the existing bear-open-note tool so callers can open a note in one step without first running bear-search-notes, including a disambiguation response when multiple notes share a title.
Changes:
- Extend
bear-open-noteto accepttitle(case-insensitive exact match) as an alternative toid, with not-found and multiple-match handling. - Add
findNotesByTitle()database helper and a lightweightNoteTitleMatchtype for disambiguation. - Add system tests covering open-by-title behavior, case-insensitive matching, disambiguation, and regression for open-by-id.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| tests/system/open-note-by-title.test.ts | Adds end-to-end system coverage for opening notes by title and related edge cases. |
| src/types.ts | Introduces NoteTitleMatch for lightweight title lookup/disambiguation results. |
| src/notes.ts | Adds findNotesByTitle() SQL query helper for case-insensitive exact title matches. |
| src/main.ts | Updates bear-open-note schema/handler to support title lookups and disambiguation responses. |
You can also share your feedback on Copilot code review. Take the survey.
| // Both IDs should appear in the disambiguation list | ||
| for (const id of noteIds) { | ||
| expect(openResult).toContain(id); | ||
| } |
There was a problem hiding this comment.
The disambiguation test asserts IDs are present but doesn’t assert that modification dates are included, which is part of the acceptance criteria. Add an assertion that the response contains a "modified:" field (or matches a date/ISO pattern) to prevent regressions in the disambiguation output.
| } | |
| } | |
| // Disambiguation entries should include modification metadata | |
| expect(openResult).toMatch(/modified\s*:/); |
There was a problem hiding this comment.
Good point — fixed in 43e2cf9. Added expect(openResult).toMatch(/modified:\s*\d{4}-\d{2}-\d{2}/) to verify date metadata is present in the disambiguation output.
src/main.ts
Outdated
| const matchList = matches | ||
| .map( | ||
| (m, i) => | ||
| `${i + 1}. ID: ${m.identifier} (modified: ${new Date(m.modification_date).toLocaleDateString()})` |
There was a problem hiding this comment.
The disambiguation output formats modification dates with toLocaleDateString(), which is locale/timezone dependent and drops the time component. This can produce inconsistent results across environments/agents. Prefer emitting the already-ISO modification_date string (or a fixed UTC/ISO format) for deterministic output.
| `${i + 1}. ID: ${m.identifier} (modified: ${new Date(m.modification_date).toLocaleDateString()})` | |
| `${i + 1}. ID: ${m.identifier} (modified: ${m.modification_date})` |
There was a problem hiding this comment.
Valid catch — fixed in 43e2cf9. Now using the ISO modification_date string directly instead of toLocaleDateString(), which gives deterministic output across environments.
Replace toLocaleDateString() with the ISO modification_date string for deterministic, locale-independent output. Add assertion that disambiguation response includes modification date metadata. Created with Claude Code under the supervision of Serhii Vasylenko
Regression guard for the ZTRASHED/ZARCHIVED/ZENCRYPTED filters in findNotesByTitle — this filter class has regressed before (bf5fe71). Created with Claude Code under the supervision of Serhii Vasylenko
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
You can also share your feedback on Copilot code review. Take the survey.
Replace length check with Set-based uniqueness assertion to catch the case where awaitNoteCreation returns the same ID twice. Created with Claude Code under the supervision of Serhii Vasylenko
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
You can also share your feedback on Copilot code review. Take the survey.
Created with Claude Code under the supervision of Serhii Vasylenko
Summary
bear-open-notenow accepts an optionaltitleparameter as an alternative toid, enabling users to open a note by its title in a single tool call without searching firstcreateToolResponse()to avoid breaking agent flowsWhy
Users frequently know the exact title of the note they want to open but currently must call
bear-search-notesfirst to resolve the ID, then callbear-open-notewith that ID. Accepting a title directly eliminates this two-step friction.--
Closes #60