Bug Description
write_note(note_type="Task") stores type: task (lowercased) in the note's frontmatter, but type matching in schema_validate and search_notes (note_types=[...]) is case-sensitive. Notes whose frontmatter says type: Task (hand-written or migrated) and notes created through write_note end up as two separate populations that no single query covers, so type-wide validation silently reports only partial results.
Steps To Reproduce
- Install Basic Memory 0.22.1 and set up a local project.
- Create a schema note for entity
Task (schema/Task.md).
- Create note A by hand with frontmatter
type: Task.
- Create note B via the MCP tool
write_note(title=..., note_type="Task", ...): its stored frontmatter reads type: task.
- Run
schema_validate(note_type="Task"), then schema_validate(note_type="task").
Expected Behavior
One logical type is one population: either write_note preserves the capitalization it was given, or type matching is case-insensitive across schema_validate / search_notes / metadata filters. Either way, a single call validates all notes of the type.
Actual Behavior
schema_validate(note_type="Task") validates only note A; schema_validate(note_type="task") validates only note B. Neither call reports the other population, and there is no warning that a differently-capitalized sibling type exists.
Environment
- OS: Windows 11 Home (10.0.26200)
- Python version: 3.14.6
- Basic Memory version: 0.22.1
- Installation method: uv tool
- Claude Desktop version: n/a (MCP tools called from Claude Code CLI)
Additional Context
Hit on 2026-08-03 while batch-migrating 25 task notes into a project that already had 8 hand-migrated notes with type: Task: validating "all tasks" required two separate calls with different capitalizations, and it is easy to believe everything was validated when only half was visible.
Possible Solution
Normalize type on write AND compare case-insensitively on read, or preserve the given capitalization end to end. Consistency in either direction fixes the split; the current mix (normalize on write, exact-match on read) is what creates the two populations.
Bug Description
write_note(note_type="Task")storestype: task(lowercased) in the note's frontmatter, but type matching inschema_validateandsearch_notes(note_types=[...]) is case-sensitive. Notes whose frontmatter saystype: Task(hand-written or migrated) and notes created throughwrite_noteend up as two separate populations that no single query covers, so type-wide validation silently reports only partial results.Steps To Reproduce
Task(schema/Task.md).type: Task.write_note(title=..., note_type="Task", ...): its stored frontmatter readstype: task.schema_validate(note_type="Task"), thenschema_validate(note_type="task").Expected Behavior
One logical type is one population: either
write_notepreserves the capitalization it was given, or type matching is case-insensitive acrossschema_validate/search_notes/ metadata filters. Either way, a single call validates all notes of the type.Actual Behavior
schema_validate(note_type="Task")validates only note A;schema_validate(note_type="task")validates only note B. Neither call reports the other population, and there is no warning that a differently-capitalized sibling type exists.Environment
Additional Context
Hit on 2026-08-03 while batch-migrating 25 task notes into a project that already had 8 hand-migrated notes with
type: Task: validating "all tasks" required two separate calls with different capitalizations, and it is easy to believe everything was validated when only half was visible.Possible Solution
Normalize
typeon write AND compare case-insensitively on read, or preserve the given capitalization end to end. Consistency in either direction fixes the split; the current mix (normalize on write, exact-match on read) is what creates the two populations.