"""Runtime bootstrap for the knowtation MCP namespace (§KD-5a.A(c)).""" from __future__ import annotations import logging import pathlib from muse.plugins.knowtation.attestation import ( load_air_config, register_knowtation_attestation_provider, ) from muse.plugins.knowtation.icp_push_hook import register_knowtation_icp_push_hook logger = logging.getLogger(__name__) _DOMAIN_IGNORE_BLOCK = """\ [domain.knowtation] patterns = [ "data/", ".obsidian/", ] """ def ensure_knowtation_museignore(root: pathlib.Path) -> None: """Ensure ``.museignore`` excludes ``data/`` and ``.obsidian/`` (§KD-5a.A(d)).""" ignore_path = root / ".museignore" if ignore_path.exists(): text = ignore_path.read_text(encoding="utf-8") if "[domain.knowtation]" in text and "data/" in text: return if "[domain.knowtation]" not in text: merged = text.rstrip() + "\n\n" + _DOMAIN_IGNORE_BLOCK ignore_path.write_text(merged, encoding="utf-8") return ignore_path.write_text( "# Muse ignore patterns\n\n" + _DOMAIN_IGNORE_BLOCK, encoding="utf-8", ) def bootstrap_knowtation_mcp(root: pathlib.Path) -> None: """Register attestation + ICP push hook at MCP server start (not ``__init__.py``). Idempotent — safe to call on every server initialisation when the active domain is ``knowtation``. Args: root: Muse repository root (contains ``.muse/``). """ ensure_knowtation_museignore(root) cfg = load_air_config(root / ".muse" / "air.yaml") register_knowtation_attestation_provider(cfg) register_knowtation_icp_push_hook() logger.debug("knowtation MCP bootstrap: attestation + ICP push hook registered") __all__ = ["bootstrap_knowtation_mcp", "ensure_knowtation_museignore"]