Add ensure_frontmatter_on_sync with precedence warning

Add a new config option to enforce frontmatter on markdown sync when missing, writing derived title/type/permalink and updating in-memory metadata before upsert. Add startup warning when this option is combined with disable_permalinks to make precedence explicit. Add config/sync/initialization tests for the new behavior, and stabilize project list CLI integration assertions by forcing a wide terminal in tests to avoid Rich truncation.

Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
phernandez
2026-02-16 22:08:09 -06:00
parent 0239f4abb4
commit a6d8d4c0f6
7 changed files with 167 additions and 6 deletions
+5
View File
@@ -231,6 +231,11 @@ class BasicMemoryConfig(BaseSettings):
description="Disable automatic permalink generation in frontmatter. When enabled, new notes won't have permalinks added and sync won't update permalinks. Existing permalinks will still work for reading.",
)
ensure_frontmatter_on_sync: bool = Field(
default=False,
description="Ensure markdown files have frontmatter during sync by adding derived title/type/permalink when missing. When combined with disable_permalinks=True, this setting takes precedence for missing-frontmatter files and still writes permalinks.",
)
permalinks_include_project: bool = Field(
default=True,
description="When True, generated permalinks are prefixed with the project slug (e.g., 'specs/search'). Existing permalinks remain unchanged unless explicitly updated.",
@@ -174,6 +174,16 @@ async def initialize_app(
Args:
app_config: The Basic Memory project configuration
"""
# Trigger: frontmatter enforcement is enabled while permalink generation is disabled
# Why: missing-frontmatter sync path needs canonical permalinks for deterministic indexing
# Outcome: log startup precedence so behavior is explicit to operators
if app_config.ensure_frontmatter_on_sync and app_config.disable_permalinks:
logger.warning(
"Config precedence: ensure_frontmatter_on_sync=True overrides "
"disable_permalinks=True for markdown files missing frontmatter during sync; "
"permalinks will be written."
)
# Trigger: database backend is Postgres (cloud deployment)
# Why: cloud deployments manage their own projects and migrations via the cloud platform.
# The local MCP server always uses SQLite and needs initialization even when
+15
View File
@@ -669,6 +669,21 @@ class SyncService:
ctime=file_metadata.created_at.timestamp(),
)
# Trigger: markdown file has no frontmatter and frontmatter enforcement is enabled
# Why: watch/sync consumers rely on normalized metadata and stable permalinks
# Outcome: file is updated in-place with derived title/type/permalink metadata
if not file_contains_frontmatter and self.app_config.ensure_frontmatter_on_sync:
permalink = await self.entity_service.resolve_permalink(
path, markdown=entity_markdown, skip_conflict_check=True
)
frontmatter_updates = {
"title": entity_markdown.frontmatter.title,
"type": entity_markdown.frontmatter.type,
"permalink": permalink,
}
await self.file_service.update_frontmatter(path, frontmatter_updates)
entity_markdown.frontmatter.metadata.update(frontmatter_updates)
# if the file contains frontmatter, resolve a permalink (unless disabled)
if file_contains_frontmatter and not self.app_config.disable_permalinks:
# Resolve permalink - skip conflict checks during bulk sync for performance