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,152 @@
1
+ """Orchestrates the 6 phases through IngestContext. Enables
2
+ `compass ingest --stop-after <phase>` for debugging."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import logging
7
+ import os
8
+ import shutil
9
+ import subprocess
10
+ from collections.abc import Callable
11
+ from datetime import UTC, datetime
12
+ from importlib.metadata import PackageNotFoundError, version
13
+ from pathlib import Path
14
+
15
+ from compass_core.graph.db import GraphDB
16
+ from compass_core.graph.schema import create_schema
17
+ from compass_core.index.locate import metadata_path_for
18
+ from compass_core.index.metadata import SCHEMA_VERSION, IndexMetadata, save_metadata
19
+ from compass_core.phases.base import IngestContext, Phase
20
+ from compass_core.phases.discovery import DiscoveryPhase
21
+ from compass_core.phases.parse import ParsePhase
22
+ from compass_core.phases.persistence import PersistencePhase
23
+ from compass_core.phases.resolution import ResolutionPhase
24
+ from compass_core.phases.symbol_table import SymbolTablePhase
25
+ from compass_core.phases.validation import ValidationPhase
26
+ from compass_core.progress import ProgressReporter
27
+ from compass_core.shared_types import Language
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ _PHASE_ORDER = ["discovery", "parse", "symbol_table", "resolution", "validation", "persistence"]
32
+
33
+ _GRAMMAR_PACKAGES: dict[Language, str] = {
34
+ Language.PYTHON: "tree-sitter-python",
35
+ }
36
+
37
+
38
+ class Pipeline:
39
+ def __init__(self, *, max_workers: int | None = None) -> None:
40
+ self._max_workers = max_workers
41
+
42
+ def run(
43
+ self,
44
+ repo_root: Path,
45
+ db_path: Path,
46
+ *,
47
+ reporter: ProgressReporter | None = None,
48
+ stop_after: str | None = None,
49
+ on_phase_complete: Callable[[str, IngestContext], None] | None = None,
50
+ ) -> IngestContext:
51
+ # Stamp the index with the time the ingest STARTS: a file edited while a long
52
+ # ingest runs has a later mtime and is reported stale, not silently trusted.
53
+ started_at = datetime.now(UTC)
54
+ ctx = IngestContext(repo_root=repo_root, reporter=reporter)
55
+
56
+ phases: dict[str, Phase] = {
57
+ "discovery": DiscoveryPhase(),
58
+ "parse": ParsePhase(max_workers=self._max_workers),
59
+ "symbol_table": SymbolTablePhase(),
60
+ "resolution": ResolutionPhase(),
61
+ "validation": ValidationPhase(),
62
+ }
63
+
64
+ for phase_name in _PHASE_ORDER:
65
+ if phase_name == "persistence":
66
+ break
67
+ ctx = phases[phase_name].run(ctx)
68
+ if on_phase_complete is not None:
69
+ on_phase_complete(phase_name, ctx)
70
+ if stop_after == phase_name:
71
+ return ctx
72
+
73
+ db_path.parent.mkdir(parents=True, exist_ok=True)
74
+ building = db_path.with_name(db_path.name + ".building")
75
+ _remove_db(building)
76
+ try:
77
+ with GraphDB(building) as db:
78
+ create_schema(db)
79
+ ctx = PersistencePhase().run(ctx, db)
80
+ os.replace(building, db_path)
81
+ except BaseException:
82
+ _remove_db(building)
83
+ raise
84
+ if on_phase_complete is not None:
85
+ on_phase_complete("persistence", ctx)
86
+
87
+ _save_metadata(repo_root, metadata_path_for(db_path), started_at)
88
+ return ctx
89
+
90
+
91
+ def _remove_db(path: Path) -> None:
92
+ """Delete a LadybugDB file or directory plus its write-ahead log, if present.
93
+
94
+ Args:
95
+ path: The database path; sibling files named ``<path>.wal`` are removed too.
96
+ """
97
+ for candidate in (path, path.with_name(path.name + ".wal")):
98
+ if candidate.is_dir():
99
+ shutil.rmtree(candidate)
100
+ elif candidate.exists():
101
+ candidate.unlink()
102
+
103
+
104
+ def _save_metadata(repo_path: Path, metadata_path: Path, indexed_at: datetime) -> None:
105
+ """Write the index metadata (commit, time, grammar versions) via IndexMetadata.
106
+
107
+ Args:
108
+ repo_path: Repository root, used for the git commit.
109
+ metadata_path: Destination beside the database (``metadata_path_for``), so
110
+ ``require_index(..., override=db_path)`` finds it; for the default
111
+ database this is ``<repo>/.compass/metadata.json``.
112
+ indexed_at: When the ingest started (taken before discovery).
113
+ """
114
+ commit = _get_git_commit(repo_path)
115
+ meta = IndexMetadata(
116
+ indexed_commit=None if commit == "unknown" else commit,
117
+ indexed_at=indexed_at,
118
+ schema_version=SCHEMA_VERSION,
119
+ grammar_versions=_grammar_versions(),
120
+ )
121
+ save_metadata(metadata_path, meta)
122
+ logger.debug("Metadata written: %s", meta)
123
+
124
+
125
+ def _get_git_commit(repo_path: Path) -> str:
126
+ """Return the HEAD commit hash, or 'unknown' on any failure."""
127
+ try:
128
+ result = subprocess.run(
129
+ ["git", "rev-parse", "HEAD"],
130
+ cwd=repo_path,
131
+ capture_output=True,
132
+ text=True,
133
+ timeout=5,
134
+ )
135
+ if result.returncode == 0:
136
+ return result.stdout.strip()
137
+ except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
138
+ pass
139
+ return "unknown"
140
+
141
+
142
+ def _grammar_versions() -> dict[Language, str]:
143
+ """Pin the installed grammar package version for every registered
144
+ language — an unpinned grammar version means incremental diffing would
145
+ trust stale data unknowingly."""
146
+ versions: dict[Language, str] = {}
147
+ for language_id, package in _GRAMMAR_PACKAGES.items():
148
+ try:
149
+ versions[language_id] = version(package)
150
+ except PackageNotFoundError:
151
+ continue
152
+ return versions