test_knowtation_mcp_unit.py python
67 lines 2.5 KB
Raw
sha256:cf6265cea8c21d9228d90dec13ef6ec2dab5103d466db9cc4590681832de4bf8 docs(KD-STAGING): sync governance after KD-6b DONE Human 13 days ago
1 """Tier 1 — unit tests for knowtation MCP schemas and helpers."""
2
3 from __future__ import annotations
4
5 import pathlib
6
7 import pytest
8
9 from muse.mcp.errors import MCPApplicationError
10 from muse.mcp.server import MuseMCPServer, expected_prompt_count, expected_tool_count
11 from muse.plugins.knowtation.mcp_helpers import validate_note_path
12 from muse.plugins.knowtation.search import hybrid_search, lexical_search
13
14
15 class TestPathValidation:
16 def test_rejects_traversal(self) -> None:
17 with pytest.raises(Exception) as exc:
18 validate_note_path("../etc/passwd.md")
19 assert exc.value.reason == "PATH_INVALID"
20
21 def test_rejects_non_note(self) -> None:
22 with pytest.raises(Exception) as exc:
23 validate_note_path("data/index.sqlite")
24 assert exc.value.reason == "NOT_A_NOTE"
25
26 def test_accepts_note(self) -> None:
27 assert validate_note_path("notes/foo.md") == "notes/foo.md"
28
29
30 class TestSearchUnit:
31 def test_lexical_empty_query(self, tmp_path: pathlib.Path) -> None:
32 assert lexical_search(tmp_path, " ") == []
33
34 def test_hybrid_shape(self, tmp_path: pathlib.Path) -> None:
35 note = tmp_path / "a.md"
36 note.write_text("---\ntitle: Alpha\n---\n# Alpha\nkeyword-here\n", encoding="utf-8")
37 out = hybrid_search(tmp_path, "keyword-here", top_k=5, mode="lexical")
38 assert out["mode"] == "lexical"
39 assert "backends" in out
40 assert "degraded" in out
41 assert isinstance(out["results"], list)
42
43
44 class TestActivationGate:
45 def test_non_knowtation_domain_empty_tools(self, tmp_path: pathlib.Path) -> None:
46 muse = tmp_path / ".muse"
47 muse.mkdir()
48 (muse / "repo.json").write_text('{"domain":"code","repo_id":"x"}', encoding="utf-8")
49 server = MuseMCPServer(tmp_path)
50 resp = server.handle_request({"jsonrpc": "2.0", "id": 1, "method": "tools/list"})
51 assert resp is not None
52 assert resp["result"]["tools"] == []
53 assert expected_tool_count("code") == 0
54 assert expected_prompt_count("knowtation") == 4
55
56 def test_knowtation_domain_lists_nine_tools(self, smoke_root: pathlib.Path) -> None:
57 server = MuseMCPServer(smoke_root)
58 resp = server.handle_request({"jsonrpc": "2.0", "id": 1, "method": "tools/list"})
59 assert resp is not None
60 names = {t["name"] for t in resp["result"]["tools"]}
61 assert len(names) == 9
62 assert "knowtation/search" in names
63
64
65 @pytest.fixture
66 def smoke_root() -> pathlib.Path:
67 return pathlib.Path("/Users/aaronrenecarvajal/MUSE_HUB/knowtation-vault-smoke")
File History 1 commit
sha256:cf6265cea8c21d9228d90dec13ef6ec2dab5103d466db9cc4590681832de4bf8 docs(KD-STAGING): sync governance after KD-6b DONE Human 13 days ago