Add codespaces skill for belief-map architecture discovery
Initial import of the codespaces skill: query .belief_map.sexp for module boundaries, dependencies, blast radius, and the minimal files to read before non-trivial code changes. Includes the belief-map and infra-topology builders, the belief-search query engine and its tests, and reference docs for the S-expression notation and query patterns.
This commit is contained in:
152
tests/test_belief_search.py
Normal file
152
tests/test_belief_search.py
Normal file
@@ -0,0 +1,152 @@
|
||||
import importlib.util
|
||||
import io
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import unittest
|
||||
from contextlib import redirect_stdout
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT_PATH = Path("/Users/alexeus/.codex/skills/codespaces/scripts/belief_search.py")
|
||||
SPEC = importlib.util.spec_from_file_location("belief_search", SCRIPT_PATH)
|
||||
belief_search = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC.loader is not None
|
||||
sys.modules[SPEC.name] = belief_search
|
||||
SPEC.loader.exec_module(belief_search)
|
||||
|
||||
|
||||
class BeliefSearchAliasTest(unittest.TestCase):
|
||||
def _load_graph(self) -> tuple[object, str]:
|
||||
tmpdir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(tmpdir.cleanup)
|
||||
|
||||
sexp_path = Path(tmpdir.name) / ".belief_map.sexp"
|
||||
sexp_path.write_text(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
(paths
|
||||
(app-service
|
||||
(app-service
|
||||
(src
|
||||
(workspace-operatives
|
||||
(asp543 workspace-operative.service)
|
||||
(asp544 workspace-operative.service.spec)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(node asp543 ts service)
|
||||
(node asp544 ts test)
|
||||
(cls asp543 WorkspaceOperativeService 16)
|
||||
(imports asp544 asp543)
|
||||
"""
|
||||
).strip()
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
graph = belief_search.BeliefGraph()
|
||||
graph.load(str(sexp_path))
|
||||
return graph, str(sexp_path)
|
||||
|
||||
def test_resolve_module_accepts_path_aliases(self) -> None:
|
||||
"""/* REQ-CS-001: analyze must accept internal path-map aliases returned by older belief maps. */"""
|
||||
graph, _sexp_path = self._load_graph()
|
||||
|
||||
self.assertEqual(
|
||||
graph.resolve_module("asp543"),
|
||||
["app-service/app-service/src/workspace-operatives/workspace-operative.service"],
|
||||
)
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_analyze(graph, "asp543")
|
||||
|
||||
self.assertIn(
|
||||
"(analyze app-service/app-service/src/workspace-operatives/workspace-operative.service",
|
||||
output.getvalue(),
|
||||
)
|
||||
|
||||
def test_search_returns_resolved_module_ids(self) -> None:
|
||||
"""/* REQ-CS-002: search must emit resolved module IDs instead of raw path-map aliases. */"""
|
||||
graph, sexp_path = self._load_graph()
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_search(graph, "workspace-operative.service", sexp_path)
|
||||
|
||||
lines = output.getvalue().strip().splitlines()
|
||||
self.assertEqual(
|
||||
lines,
|
||||
[
|
||||
"(result app-service/app-service/src/workspace-operatives/workspace-operative.service)",
|
||||
"(result app-service/app-service/src/workspace-operatives/workspace-operative.service.spec)",
|
||||
"(result-count 2)",
|
||||
],
|
||||
)
|
||||
|
||||
def test_quick_runs_analyze_for_first_resolved_module(self) -> None:
|
||||
"""/* REQ-CS-003: quick must provide full analyze output for the first matching module. */"""
|
||||
graph, sexp_path = self._load_graph()
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_quick(graph, "workspace-operative.service", sexp_path)
|
||||
|
||||
text = output.getvalue()
|
||||
self.assertIn(
|
||||
"(analyze app-service/app-service/src/workspace-operatives/workspace-operative.service",
|
||||
text,
|
||||
)
|
||||
self.assertIn(
|
||||
"(boundary-file app-service/app-service/src/workspace-operatives/workspace-operative.service",
|
||||
text,
|
||||
)
|
||||
self.assertNotIn("(boundary app-service/app-service/src/workspace-operatives/workspace-operative.service", text)
|
||||
|
||||
def test_quick_resolves_alias_from_raw_search_hits(self) -> None:
|
||||
"""/* REQ-CS-004: quick must resolve legacy path-map aliases found in raw belief-map facts. */"""
|
||||
graph, sexp_path = self._load_graph()
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_quick(graph, "WorkspaceOperativeService", sexp_path)
|
||||
|
||||
self.assertIn(
|
||||
"(analyze app-service/app-service/src/workspace-operatives/workspace-operative.service",
|
||||
output.getvalue(),
|
||||
)
|
||||
|
||||
def test_boundary_files_only_emits_minimal_file_list(self) -> None:
|
||||
"""/* REQ-CS-005: boundary --files-only must emit the target and directly related files only. */"""
|
||||
graph, _sexp_path = self._load_graph()
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_boundary(graph, "workspace-operative.service", files_only=True)
|
||||
|
||||
self.assertEqual(
|
||||
output.getvalue().strip().splitlines(),
|
||||
[
|
||||
"app-service/app-service/src/workspace-operatives/workspace-operative.service",
|
||||
"app-service/app-service/src/workspace-operatives/workspace-operative.service.spec",
|
||||
],
|
||||
)
|
||||
|
||||
def test_no_match_includes_suggestions(self) -> None:
|
||||
"""/* REQ-CS-006: no-match errors must surface actionable module suggestions. */"""
|
||||
graph, _sexp_path = self._load_graph()
|
||||
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
belief_search.cmd_analyze(graph, "workspace-operative.controller")
|
||||
|
||||
text = output.getvalue()
|
||||
self.assertIn("(error no-match workspace-operative.controller :suggestions", text)
|
||||
self.assertIn("workspace-operative.service", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user