compass-code 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. compass_cli/__init__.py +0 -0
  2. compass_cli/commands/__init__.py +0 -0
  3. compass_cli/commands/ingest.py +310 -0
  4. compass_cli/commands/mcp.py +25 -0
  5. compass_cli/commands/query.py +181 -0
  6. compass_cli/commands/serve.py +123 -0
  7. compass_cli/commands/setup.py +171 -0
  8. compass_cli/display.py +231 -0
  9. compass_cli/errors.py +30 -0
  10. compass_cli/main.py +54 -0
  11. compass_cli/progress.py +191 -0
  12. compass_cli/result_views.py +389 -0
  13. compass_cli/types.py +41 -0
  14. compass_code-0.1.0.dist-info/METADATA +72 -0
  15. compass_code-0.1.0.dist-info/RECORD +137 -0
  16. compass_code-0.1.0.dist-info/WHEEL +4 -0
  17. compass_code-0.1.0.dist-info/entry_points.txt +2 -0
  18. compass_core/__init__.py +1 -0
  19. compass_core/contract/__init__.py +6 -0
  20. compass_core/contract/errors.py +116 -0
  21. compass_core/contract/models.py +204 -0
  22. compass_core/contract/params.py +99 -0
  23. compass_core/contract/results.py +370 -0
  24. compass_core/contract/serialize.py +59 -0
  25. compass_core/contract/types.py +76 -0
  26. compass_core/errors.py +148 -0
  27. compass_core/graph/__init__.py +0 -0
  28. compass_core/graph/db.py +205 -0
  29. compass_core/graph/schema.py +165 -0
  30. compass_core/graph/stored_ids.py +133 -0
  31. compass_core/graph/writer.py +482 -0
  32. compass_core/index/__init__.py +1 -0
  33. compass_core/index/freshness.py +55 -0
  34. compass_core/index/locate.py +155 -0
  35. compass_core/index/metadata.py +107 -0
  36. compass_core/ir/__init__.py +0 -0
  37. compass_core/ir/graph.py +65 -0
  38. compass_core/ir/models.py +75 -0
  39. compass_core/languages/__init__.py +1 -0
  40. compass_core/languages/base.py +26 -0
  41. compass_core/languages/python/__init__.py +6 -0
  42. compass_core/languages/python/extractor.py +670 -0
  43. compass_core/languages/python/import_resolver.py +107 -0
  44. compass_core/languages/registry.py +89 -0
  45. compass_core/logger.py +42 -0
  46. compass_core/phases/__init__.py +0 -0
  47. compass_core/phases/base.py +58 -0
  48. compass_core/phases/discovery.py +167 -0
  49. compass_core/phases/parse.py +80 -0
  50. compass_core/phases/persistence.py +33 -0
  51. compass_core/phases/pipeline.py +152 -0
  52. compass_core/phases/resolution.py +572 -0
  53. compass_core/phases/symbol_table.py +36 -0
  54. compass_core/phases/validation.py +76 -0
  55. compass_core/progress.py +45 -0
  56. compass_core/py.typed +0 -0
  57. compass_core/query/__init__.py +1 -0
  58. compass_core/query/cypher.py +92 -0
  59. compass_core/query/detail.py +241 -0
  60. compass_core/query/graph_map.py +127 -0
  61. compass_core/query/impact.py +273 -0
  62. compass_core/query/impact_walk.py +352 -0
  63. compass_core/query/overview.py +221 -0
  64. compass_core/query/references.py +235 -0
  65. compass_core/query/rows.py +378 -0
  66. compass_core/query/search.py +183 -0
  67. compass_core/query/status.py +49 -0
  68. compass_core/query/walk_queries.py +202 -0
  69. compass_core/render.py +408 -0
  70. compass_core/settings.py +61 -0
  71. compass_core/shared_types.py +78 -0
  72. compass_mcp/__init__.py +0 -0
  73. compass_mcp/guide.py +45 -0
  74. compass_mcp/py.typed +0 -0
  75. compass_mcp/server.py +261 -0
  76. compass_server/__init__.py +5 -0
  77. compass_server/errors.py +84 -0
  78. compass_server/main.py +42 -0
  79. compass_server/py.typed +0 -0
  80. compass_server/routers/__init__.py +0 -0
  81. compass_server/routers/query.py +182 -0
  82. compass_server/settings.py +37 -0
  83. compass_server/static/404.html +1 -0
  84. compass_server/static/_next/static/chunks/1629039a.eed2a06658ec4f9c.js +1 -0
  85. compass_server/static/_next/static/chunks/1ff282bf-bb7c483245264fc9.js +1 -0
  86. compass_server/static/_next/static/chunks/223.f881a22f446259bf.js +508 -0
  87. compass_server/static/_next/static/chunks/51fa5c19.6396973222c9d6fd.js +485 -0
  88. compass_server/static/_next/static/chunks/556.443c1682b6b20128.js +1 -0
  89. compass_server/static/_next/static/chunks/684-1aa0170f59baf77e.js +1 -0
  90. compass_server/static/_next/static/chunks/92e71660.3a42d4f70d017951.js +342 -0
  91. compass_server/static/_next/static/chunks/937-8692224bb6d1b605.js +1 -0
  92. compass_server/static/_next/static/chunks/app/_not-found/page-2c96ddf295eb6a86.js +1 -0
  93. compass_server/static/_next/static/chunks/app/layout-4bd0ba4a7d18aff9.js +1 -0
  94. compass_server/static/_next/static/chunks/app/page-5376a0a98bbd1faa.js +1 -0
  95. compass_server/static/_next/static/chunks/framework-96dcd958cfe08bd4.js +1 -0
  96. compass_server/static/_next/static/chunks/main-6dee8e626b16731a.js +1 -0
  97. compass_server/static/_next/static/chunks/main-app-460e8bc670818718.js +1 -0
  98. compass_server/static/_next/static/chunks/pages/_app-638a3e7363f92b80.js +1 -0
  99. compass_server/static/_next/static/chunks/pages/_error-6a72dbbb45cae743.js +1 -0
  100. compass_server/static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  101. compass_server/static/_next/static/chunks/webpack-597057bf48ce4111.js +1 -0
  102. compass_server/static/_next/static/css/1b0fbfd8dd653f37.css +3 -0
  103. compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_buildManifest.js +1 -0
  104. compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_ssgManifest.js +1 -0
  105. compass_server/static/_next/static/media/0086f8992871c45b-s.woff2 +0 -0
  106. compass_server/static/_next/static/media/034d78ad42e9620c-s.woff2 +0 -0
  107. compass_server/static/_next/static/media/03b436aa846269de-s.woff2 +0 -0
  108. compass_server/static/_next/static/media/0484562807a97172-s.p.woff2 +0 -0
  109. compass_server/static/_next/static/media/08aedeceaf1dcd57-s.woff2 +0 -0
  110. compass_server/static/_next/static/media/0aa834ed78bf6d07-s.woff2 +0 -0
  111. compass_server/static/_next/static/media/29a4aea02fdee119-s.woff2 +0 -0
  112. compass_server/static/_next/static/media/29e7bbdce9332268-s.woff2 +0 -0
  113. compass_server/static/_next/static/media/36008747766f78c6-s.woff2 +0 -0
  114. compass_server/static/_next/static/media/39969fcf98a3026e-s.woff2 +0 -0
  115. compass_server/static/_next/static/media/4de1fea1a954a5b6-s.p.woff2 +0 -0
  116. compass_server/static/_next/static/media/5c0c2bcbaa4149ca-s.p.woff2 +0 -0
  117. compass_server/static/_next/static/media/67957d42bae0796d-s.woff2 +0 -0
  118. compass_server/static/_next/static/media/6d38f9d4e0f4772b-s.woff2 +0 -0
  119. compass_server/static/_next/static/media/6d664cce900333ee-s.p.woff2 +0 -0
  120. compass_server/static/_next/static/media/886030b0b59bc5a7-s.woff2 +0 -0
  121. compass_server/static/_next/static/media/8888a3826f4a3af4-s.p.woff2 +0 -0
  122. compass_server/static/_next/static/media/939c4f875ee75fbb-s.woff2 +0 -0
  123. compass_server/static/_next/static/media/a1386beebedccca4-s.woff2 +0 -0
  124. compass_server/static/_next/static/media/ab00a911ac2adf48-s.woff2 +0 -0
  125. compass_server/static/_next/static/media/b957ea75a84b6ea7-s.p.woff2 +0 -0
  126. compass_server/static/_next/static/media/bb3ef058b751a6ad-s.p.woff2 +0 -0
  127. compass_server/static/_next/static/media/c3bc380753a8436c-s.woff2 +0 -0
  128. compass_server/static/_next/static/media/cce080f35d014443-s.woff2 +0 -0
  129. compass_server/static/_next/static/media/db911767852bc875-s.woff2 +0 -0
  130. compass_server/static/_next/static/media/eafabf029ad39a43-s.p.woff2 +0 -0
  131. compass_server/static/_next/static/media/f10b8e9d91f3edcb-s.woff2 +0 -0
  132. compass_server/static/_next/static/media/f911b923c6adde36-s.woff2 +0 -0
  133. compass_server/static/_next/static/media/fe0777f1195381cb-s.woff2 +0 -0
  134. compass_server/static/index.html +1 -0
  135. compass_server/static/index.txt +25 -0
  136. compass_server/web_bundle.py +27 -0
  137. compass_server/web_limits.py +48 -0
@@ -0,0 +1,107 @@
1
+ """Typed read/write of ``.compass/metadata.json``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from collections.abc import Mapping
8
+ from dataclasses import dataclass
9
+ from datetime import UTC, datetime
10
+ from pathlib import Path
11
+
12
+ from compass_core.errors import IndexIncompatibleError
13
+ from compass_core.shared_types import Language
14
+
15
+ SCHEMA_VERSION = 2
16
+ """Graph schema written by this version of compass; indexes in any other version are
17
+ rejected and must be rebuilt with ``compass ingest``.
18
+
19
+ History: 1 stored internal ids (``py::app.models::User``); 2 stores public ids
20
+ (``app/models.py::User``) and a ``qualified_name`` on classes and functions.
21
+ """
22
+
23
+
24
+ @dataclass(frozen=True, slots=True, kw_only=True)
25
+ class IndexMetadata:
26
+ """Facts recorded about an index at ingest time.
27
+
28
+ Attributes:
29
+ indexed_commit: Git HEAD commit at ingest, or ``None`` if unknown.
30
+ indexed_at: Ingest time (timezone-aware).
31
+ schema_version: Metadata/index schema version; pre-v1 files count as 1.
32
+ grammar_versions: Installed grammar package version per language.
33
+
34
+ Example:
35
+ ``{"indexed_commit": "abc", "indexed_at": 1788431823, "grammar_versions":
36
+ {"python": "0.25.0"}}`` loads as ``IndexMetadata(indexed_commit="abc",
37
+ indexed_at=datetime(..., tzinfo=UTC), schema_version=2,
38
+ grammar_versions={Language.PYTHON: "0.25.0"})``.
39
+ """
40
+
41
+ indexed_commit: str | None
42
+ indexed_at: datetime
43
+ schema_version: int
44
+ grammar_versions: Mapping[Language, str]
45
+
46
+
47
+ def save_metadata(path: Path, meta: IndexMetadata) -> None:
48
+ """Atomically write ``meta`` to ``path`` as JSON.
49
+
50
+ Args:
51
+ path: Destination ``metadata.json``; parent directories are created.
52
+ meta: Metadata to store. ``indexed_at`` is stored as epoch seconds.
53
+ """
54
+ payload = {
55
+ "schema_version": meta.schema_version,
56
+ "indexed_commit": meta.indexed_commit,
57
+ "indexed_at": int(meta.indexed_at.timestamp()),
58
+ "grammar_versions": {lang.value: v for lang, v in meta.grammar_versions.items()},
59
+ }
60
+ path.parent.mkdir(parents=True, exist_ok=True)
61
+ tmp = path.with_name(f"{path.name}.{os.getpid()}.tmp")
62
+ try:
63
+ tmp.write_text(json.dumps(payload, indent=2), encoding="utf-8")
64
+ os.replace(tmp, path)
65
+ except BaseException:
66
+ tmp.unlink(missing_ok=True)
67
+ raise
68
+
69
+
70
+ def load_metadata(path: Path) -> IndexMetadata:
71
+ """Read metadata from ``path``.
72
+
73
+ Args:
74
+ path: Path to ``metadata.json``.
75
+
76
+ Returns:
77
+ The parsed metadata. A missing ``schema_version`` counts as 1.
78
+
79
+ Raises:
80
+ IndexIncompatibleError: If the file is unreadable, malformed, has an unknown
81
+ language, or its ``schema_version`` is not ``SCHEMA_VERSION``.
82
+ """
83
+ try:
84
+ raw = json.loads(path.read_text(encoding="utf-8"))
85
+ schema_version = raw.get("schema_version", 1)
86
+ if isinstance(schema_version, bool) or not isinstance(schema_version, int):
87
+ raise ValueError(f"invalid schema_version {schema_version!r}")
88
+ if schema_version != SCHEMA_VERSION:
89
+ raise IndexIncompatibleError(
90
+ f"The index at {path.parent} uses schema version {schema_version}; this "
91
+ f"compass reads version {SCHEMA_VERSION}. Run `compass ingest` to rebuild it."
92
+ )
93
+ indexed_at = raw["indexed_at"]
94
+ if isinstance(indexed_at, bool) or not isinstance(indexed_at, int | float):
95
+ raise ValueError(f"invalid indexed_at {indexed_at!r}")
96
+ commit = raw.get("indexed_commit")
97
+ return IndexMetadata(
98
+ indexed_commit=None if commit is None else str(commit),
99
+ indexed_at=datetime.fromtimestamp(indexed_at, UTC),
100
+ schema_version=schema_version,
101
+ grammar_versions={
102
+ Language(lang): str(v) for lang, v in raw.get("grammar_versions", {}).items()
103
+ },
104
+ )
105
+ except (OSError, KeyError, ValueError, TypeError, AttributeError, OverflowError) as exc:
106
+ # JSONDecodeError is a ValueError subclass.
107
+ raise IndexIncompatibleError(f"Unreadable index metadata at {path}: {exc}") from exc
File without changes
@@ -0,0 +1,65 @@
1
+ """Resolved call/import/inheritance graph — Phase 3 output, Phase 5 input.
2
+
3
+ Edge shapes are kept as four distinct dataclasses (not collapsed into one
4
+ generic Edge type) because call_resolver's 10 prioritized resolution rules
5
+ carry different fields per edge kind (external edges have no callee_id,
6
+ only a full_ref + library) and collapsing would lose that without gaining
7
+ anything — this mirrors resolver/models.py exactly, just relocated.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass, field
13
+
14
+ from compass_core.ir.models import ParsedFile
15
+ from compass_core.shared_types import CallType, UnlinkedCall
16
+
17
+ CONFIDENCE: dict[CallType | UnlinkedCall, float] = {
18
+ CallType.DIRECT_IMPORT: 1.0,
19
+ CallType.MODULE_ATTR: 0.9,
20
+ CallType.RE_EXPORT: 0.8,
21
+ CallType.MRO: 0.8,
22
+ UnlinkedCall.WILDCARD: 0.6,
23
+ UnlinkedCall.DYNAMIC: 0.0,
24
+ UnlinkedCall.CIRCULAR: 0.0,
25
+ UnlinkedCall.EXTERNAL: 0.0,
26
+ UnlinkedCall.UNRESOLVED: 0.0,
27
+ }
28
+
29
+
30
+ @dataclass(slots=True)
31
+ class CallEdge:
32
+ caller_id: str
33
+ callee_id: str
34
+ call_type: CallType
35
+ confidence: float
36
+ line: int = 0
37
+
38
+
39
+ @dataclass(slots=True)
40
+ class ExternalCallEdge:
41
+ caller_id: str
42
+ full_ref: str
43
+ library: str
44
+ line: int = 0
45
+
46
+
47
+ @dataclass(slots=True)
48
+ class ImportEdge:
49
+ from_path: str
50
+ to_path: str
51
+
52
+
53
+ @dataclass(slots=True)
54
+ class InheritEdge:
55
+ child_id: str
56
+ parent_id: str
57
+
58
+
59
+ @dataclass
60
+ class ResolvedGraph:
61
+ files: list[ParsedFile] = field(default_factory=list)
62
+ call_edges: list[CallEdge] = field(default_factory=list)
63
+ external_call_edges: list[ExternalCallEdge] = field(default_factory=list)
64
+ import_edges: list[ImportEdge] = field(default_factory=list)
65
+ inherit_edges: list[InheritEdge] = field(default_factory=list)
@@ -0,0 +1,75 @@
1
+ """Language-agnostic IR — the seam below which no phase may know a specific language.
2
+
3
+ Definition covers class/function/method (var/interface/struct are future
4
+ kinds, added when a language that needs them is registered — do not add
5
+ unused kinds speculatively).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass
11
+
12
+ from compass_core.shared_types import CallType, DefinitionKind, Language, UnlinkedCall
13
+
14
+
15
+ @dataclass(slots=True)
16
+ class Definition:
17
+ id: str # namespaced, e.g. "py::pkg.mod::Foo" or "py::pkg.mod::Foo.bar"
18
+ kind: DefinitionKind
19
+ name: str
20
+ file_path: str
21
+ line_start: int
22
+ line_end: int
23
+ source: str
24
+ docstring: str | None
25
+ bases: list[str] # populated for CLASS only
26
+ parent_id: str | None # populated for METHOD only (id of owning CLASS Definition)
27
+ signature: str | None # populated for FUNCTION/METHOD only
28
+ decorators: list[str]
29
+ raw_calls: list[str] # populated for FUNCTION/METHOD only
30
+
31
+
32
+ @dataclass(slots=True)
33
+ class ImportStatement:
34
+ module: str
35
+ names: list[str]
36
+ alias: str | None
37
+ is_relative: bool
38
+ is_from: bool
39
+ line: int
40
+
41
+
42
+ @dataclass(slots=True)
43
+ class CallSite:
44
+ callee_name: str
45
+ receiver_expr: str | None
46
+ line: int
47
+ enclosing_definition_id: str | None
48
+
49
+
50
+ @dataclass
51
+ class ParsedFile:
52
+ path: str
53
+ language: Language
54
+ module_name: str
55
+ content_hash: str
56
+ definitions: list[Definition]
57
+ imports: list[ImportStatement]
58
+ call_sites: list[CallSite]
59
+ degraded: bool = False
60
+ error: str | None = None # human-readable reason when degraded=True
61
+
62
+
63
+ @dataclass(slots=True)
64
+ class CallResult:
65
+ """Outcome of resolving one raw call string (Phase 3 / resolution.py).
66
+
67
+ Relocated from resolver/call_resolver.py::CallResult, same shape, since
68
+ it's a shared IR-adjacent type this phase produces internally.
69
+ """
70
+
71
+ raw: str
72
+ target_id: str | None # Definition.id if resolved internally
73
+ call_type: CallType | UnlinkedCall
74
+ confidence: float
75
+ external_library: str | None = None # set only for EXTERNAL calls
@@ -0,0 +1 @@
1
+ from compass_core.languages import python as _python # noqa: F401
@@ -0,0 +1,26 @@
1
+ """Plugin contracts. Every language extractor/import resolver must satisfy
2
+ these Protocols — enforced by mypy --strict in CI (Task 16), not just at
3
+ review time."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from pathlib import Path
8
+ from typing import Protocol, runtime_checkable
9
+
10
+ from compass_core.ir.models import ParsedFile
11
+ from compass_core.shared_types import Language
12
+
13
+
14
+ @runtime_checkable
15
+ class LanguageExtractor(Protocol):
16
+ language_id: Language
17
+ file_extensions: set[str]
18
+
19
+ def parse(self, source: bytes, file_path: Path) -> ParsedFile: ...
20
+
21
+
22
+ @runtime_checkable
23
+ class ImportResolver(Protocol):
24
+ language_id: Language
25
+
26
+ def resolve(self, files: list[ParsedFile]) -> dict[str, dict[str, str | None]]: ...
@@ -0,0 +1,6 @@
1
+ from compass_core.languages import registry
2
+ from compass_core.languages.python.extractor import PythonExtractor
3
+ from compass_core.languages.python.import_resolver import PythonImportResolver
4
+
5
+ registry.register_extractor(PythonExtractor())
6
+ registry.register_import_resolver(PythonImportResolver())