WIP simplifying load/startup

This commit is contained in:
John Lancaster
2026-07-26 17:23:39 -05:00
parent 5e20f69cfe
commit 42ea105bee
30 changed files with 855 additions and 766 deletions
@@ -8,8 +8,9 @@ import yaml
from pydantic import ValidationError
from personal_mcp.registry.ingest.document import MarkdownDocument
from personal_mcp.registry.load import _parse_frontmatter
from personal_mcp.registry.models.common import _normalize_docs_path
from personal_mcp.registry.models.common import ReferenceEntry
from personal_mcp.registry.models.common import parse_docs_path
from personal_mcp.registry.models.common import parse_reference_path
from personal_mcp.registry.models.registry import DocsRegistry
pytestmark = pytest.mark.unit
@@ -95,37 +96,43 @@ def assert_model_is_frozen(instance: Any, *, attr: str, value: Any) -> None:
setattr(instance, attr, value)
class TestGate1LayoutValidation:
"""Gate 1: source layout and parse shape constraints."""
def test_parse_frontmatter_requires_payload(self) -> None:
"""Ensures missing frontmatter fails before metadata validation."""
with pytest.raises(ValueError, match="missing YAML frontmatter"):
_parse_frontmatter(None, path=PurePosixPath("skills/alpha/SKILL.md"))
def test_parse_frontmatter_requires_mapping(self) -> None:
"""Ensures non-object YAML payloads are rejected at parse time."""
with pytest.raises(TypeError, match="frontmatter must parse to an object"):
_parse_frontmatter("- one\n- two\n", path=PurePosixPath("skills/alpha/SKILL.md"))
def test_parse_frontmatter_accepts_mapping(self) -> None:
"""Ensures valid mapping payload is returned for downstream validation."""
parsed = _parse_frontmatter("name: alpha\n", path=PurePosixPath("skills/alpha/SKILL.md"))
assert parsed == {"name": "alpha"}
class TestGate5ContractValidation:
"""Gate 5: canonical resource-path contract normalization."""
"""Gate 5: canonical resource-path contracts."""
def test_normalize_docs_path_keeps_posix_relative_paths(self) -> None:
"""Ensures docs paths remain normalized before registry publication."""
assert _normalize_docs_path("skills/demo/SKILL.md") == "skills/demo/SKILL.md"
def test_parse_docs_path_returns_pure_posix_path(self) -> None:
"""Ensures boundary strings become path objects before publication."""
path = parse_docs_path("skills/demo/SKILL.md")
def test_normalize_docs_path_rejects_parent_traversal(self) -> None:
"""Ensures traversal attempts fail contract validation."""
with pytest.raises(ValueError, match="normalized docs-relative path"):
_normalize_docs_path("../outside.md")
assert path == PurePosixPath("skills/demo/SKILL.md")
assert isinstance(path, PurePosixPath)
@pytest.mark.parametrize(
"value",
(
"/absolute.md",
"../outside.md",
"skills\\demo\\SKILL.md",
"skills//demo/SKILL.md",
"skills/demo/README.txt",
),
)
def test_parse_docs_path_rejects_invalid_paths(self, value: str) -> None:
"""Ensures non-canonical docs paths fail contract validation."""
with pytest.raises(ValueError):
parse_docs_path(value)
def test_reference_entry_materializes_reference_path(self) -> None:
"""Ensures authored reference strings become constrained path objects."""
entry = ReferenceEntry.model_validate({"path": "references/guides/setup.md"})
assert entry.path == PurePosixPath("references/guides/setup.md")
assert parse_reference_path(entry.path) == entry.path
@pytest.mark.parametrize("value", ("guide.md", "other/guide.md", "references.md"))
def test_reference_path_stays_under_references(self, value: str) -> None:
"""Ensures in-skill references remain below the references directory."""
with pytest.raises(ValueError, match="stay under references"):
parse_reference_path(value)
class TestGate6FreezeValidation:
@@ -133,13 +140,14 @@ class TestGate6FreezeValidation:
def test_docs_registry_copies_mapping_inputs(self) -> None:
"""Ensures registry snapshots are isolated from caller-owned mapping mutations."""
source_docs = {"index.md": "# index\n"}
index_path = PurePosixPath("index.md")
source_docs = {index_path: "# index\n"}
registry = DocsRegistry(
skills_by_id={},
skills_in_load_order=(),
skills_summary_in_load_order=(),
docs_markdown_by_path=source_docs,
docs_markdown_path_index=("index.md",),
docs_markdown_path_index=(index_path,),
tag_to_skill_ids={},
capability_to_skill_ids={},
prompts_by_id={},
@@ -148,9 +156,10 @@ class TestGate6FreezeValidation:
tag_to_prompt_ids={},
)
source_docs["other.md"] = "# other\n"
source_docs[PurePosixPath("other.md")] = "# other\n"
assert "other.md" not in registry.docs_markdown_by_path
assert PurePosixPath("other.md") not in registry.docs_markdown_by_path
assert registry.docs_markdown_path_index == (index_path,)
def test_docs_registry_instance_is_frozen(self) -> None:
"""Ensures frozen model prevents attribute reassignment."""
@@ -168,4 +177,8 @@ class TestGate6FreezeValidation:
tag_to_prompt_ids={},
)
assert_model_is_frozen(registry, attr="docs_markdown_path_index", value=("index.md",))
assert_model_is_frozen(
registry,
attr="docs_markdown_path_index",
value=(PurePosixPath("index.md"),),
)