frontmatter.Post.__init__ takes `content` and `handler` as positional
parameters. When user YAML frontmatter contains these as field names,
unpacking metadata via **kwargs causes "got multiple values for argument
'content'".
Replace frontmatter.loads() with frontmatter.parse() + Post() + update()
in entity_parser, and replace the **metadata unpacking in
entity_service.update_entity() with the same safe pattern.
Fixes basic-memory-cloud#375
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
YAML block sequence syntax can cause PyYAML to parse scalar fields like
`title` and `type` as lists instead of strings. Downstream code calls
.strip()/.casefold() on these values, crashing with
"'list' object has no attribute 'strip'".
Add _coerce_to_string() helper that joins list items with ", " and apply
it in entity_parser.parse_markdown_content() and
entity_service.fast_edit_entity() where these fields are extracted.
Fixes basic-memory-cloud#376
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Denormalizes project_id onto Relation and Observation tables to enable
efficient project-scoped queries without joins. Migration backfills
from associated entity and adds pg_trgm extension with GIN indexes
for fuzzy link resolution on PostgreSQL.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Add optimized repository methods for resolve_permalink() that skip
eager loading of observations and relations:
- permalink_exists(): Check existence without loading entity
- get_file_path_for_permalink(): Get only file_path column
- get_permalink_for_file_path(): Get only permalink column
- get_all_permalinks(): Get all permalinks as strings
- get_permalink_to_file_path_map(): Bulk lookup mapping
- get_file_path_to_permalink_map(): Reverse mapping
Updated entity_service.resolve_permalink() to use these lightweight
methods instead of loading full entities with all relationships.
Also added logfire instrumentation to markdown utils.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Fixes critical data loss bug where creating similar entity names
(e.g., "Node C") would overwrite existing entities (e.g., "Node A.md")
due to fuzzy search incorrectly matching similar file paths.
Changes:
- Add strict=True to resolve_link() calls in entity_service.py
- Disables fuzzy search fallback during entity creation/update
- Prevents false positive matches on similar paths like
"edge-cases/Node A.md" and "edge-cases/Node C.md"
Testing:
- Added comprehensive integration test reproducing the bug scenario
- Added MCP-level permalink collision tests
- All 55 entity service tests pass
- Manual testing confirms fix prevents file overwrite
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Fixes#36 by modifying entity_service.update_entity() to read existing
frontmatter from files before updating them. Custom metadata fields
such as Status, Priority, and Version are now preserved when notes
are updated through the write_note MCP tool.
Added test case that verifies this behavior by creating a note with
custom frontmatter and then updating it.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Fixes#36 by modifying entity_service.update_entity() to read existing
frontmatter from files before updating them. Custom metadata fields
such as Status, Priority, and Version are now preserved when notes
are updated through the write_note MCP tool.
Added test case that verifies this behavior by creating a note with
custom frontmatter and then updating it.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>