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,389 @@
1
+ """Rich views of query results, for a person reading them in a terminal.
2
+
3
+ The query commands print these only when stdout is a terminal. Piped output (scripts,
4
+ coding agents running ``compass`` in a shell) keeps the compact one-line-per-item text
5
+ from ``compass_core.render``, which is cheaper to read and easy to grep. Both show the same
6
+ facts; only the layout differs.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from collections.abc import Iterable, Sequence
12
+
13
+ from rich import box
14
+ from rich.console import Group, RenderableType
15
+ from rich.panel import Panel
16
+ from rich.table import Table
17
+ from rich.text import Text
18
+
19
+ from compass_cli.display import GOLD
20
+ from compass_core.contract.models import Caveat, IndexStatus, ResultItem, SymbolRef
21
+ from compass_core.contract.results import (
22
+ ImpactResult,
23
+ NodeDetail,
24
+ OverviewResult,
25
+ RankedSymbol,
26
+ SearchResult,
27
+ )
28
+ from compass_core.contract.types import CaveatCode
29
+ from compass_core.render import local_name, location, match_reason, plural, via_text
30
+ from compass_core.shared_types import EdgeType, SymbolKind
31
+
32
+ EDGE_LABELS: dict[EdgeType, str] = {
33
+ EdgeType.CONTAINS: "Contains",
34
+ EdgeType.IMPORTS: "Imports",
35
+ EdgeType.INHERITS: "Inherits",
36
+ EdgeType.CALLS: "Calls",
37
+ EdgeType.CALLS_EXTERN: "External calls",
38
+ }
39
+ """Row label for each edge type in the overview totals."""
40
+
41
+ _NO_WRAP = frozenset({"Location", "File", "Kind", "Hops"})
42
+ """Columns kept on one line; narrow terminals wrap the others first."""
43
+
44
+ _LABEL_WIDTH = 13
45
+ """Width of the dim label column in key/value grids, matching the ingest summary."""
46
+
47
+
48
+ def _title(text: str) -> Text:
49
+ return Text(text, style=f"bold {GOLD}")
50
+
51
+
52
+ def _location(symbol: SymbolRef) -> Text:
53
+ """``path:line`` with the directory dimmed, so the file name stands out."""
54
+ where = location(symbol)
55
+ directory, slash, rest = where.rpartition("/")
56
+ text = Text(overflow="fold")
57
+ if slash:
58
+ text.append(directory + slash, style="dim")
59
+ text.append(rest)
60
+ return text
61
+
62
+
63
+ def _name(symbol: SymbolRef) -> Text:
64
+ """The name within its file, last part bold (``User.`` **save**); a file's base name."""
65
+ prefix, dot, last = local_name(symbol).rpartition(".")
66
+ text = Text(overflow="fold")
67
+ if dot and symbol.kind is not SymbolKind.FILE:
68
+ text.append(prefix + dot, style="dim")
69
+ text.append(last, style="bold")
70
+ else:
71
+ text.append(local_name(symbol).rpartition("/")[2], style="bold")
72
+ return text
73
+
74
+
75
+ def _table(*headers: str, numeric: Sequence[str] = ()) -> Table:
76
+ table = Table(box=box.SIMPLE_HEAD, header_style="dim", show_edge=False, pad_edge=False)
77
+ for header in headers:
78
+ table.add_column(
79
+ header,
80
+ justify="right" if header in numeric else "left",
81
+ no_wrap=header in _NO_WRAP,
82
+ )
83
+ return table
84
+
85
+
86
+ def _section(title: str, body: RenderableType) -> Group:
87
+ return Group(Text(""), _title(title), body)
88
+
89
+
90
+ def _caveats(caveats: Iterable[Caveat]) -> list[Text]:
91
+ """Caveats in yellow; a stale index is already flagged by ``index_line``."""
92
+ return [
93
+ Text(f"! {caveat.message}", style="yellow")
94
+ for caveat in caveats
95
+ if caveat.code is not CaveatCode.STALE_INDEX
96
+ ]
97
+
98
+
99
+ def _more(shown: int, total: int) -> list[Text]:
100
+ hidden = total - shown
101
+ if hidden <= 0:
102
+ return []
103
+ return [Text(f"… {hidden:,} more; raise --limit to see them", style="dim")]
104
+
105
+
106
+ def _freshness(status: IndexStatus) -> Text:
107
+ if status.stale_file_count:
108
+ changed = plural(status.stale_file_count, "file")
109
+ return Text(f"⚠ {changed} changed since; run compass ingest", style="yellow")
110
+ return Text("✓ up to date", style="green")
111
+
112
+
113
+ def index_line(status: IndexStatus) -> Text:
114
+ """One dim line saying which index answered and whether it is fresh.
115
+
116
+ Args:
117
+ status: The index status every result carries.
118
+
119
+ Returns:
120
+ The line, e.g. ``index 5610406 · built 2026-11-10 09:30 UTC · ✓ up to date``.
121
+ """
122
+ commit = status.indexed_commit[:7] if status.indexed_commit else "no git commit"
123
+ built = status.indexed_at.strftime("%Y-%m-%d %H:%M UTC")
124
+ line = Text(f"index {commit} · built {built} · ", style="dim")
125
+ line.append_text(_freshness(status))
126
+ return line
127
+
128
+
129
+ def status_view(status: IndexStatus) -> Panel:
130
+ """The index: which repository, which commit, when it was built and if it is fresh.
131
+
132
+ Args:
133
+ status: The index status.
134
+
135
+ Returns:
136
+ A gold panel with one labelled row per fact.
137
+
138
+ Example:
139
+ ``Repository /home/me/app``, ``Commit 5610406``, ``Built 2026-11-10 09:30 UTC``
140
+ and ``Status ✓ up to date``.
141
+ """
142
+ grid = Table.grid(padding=(0, 3))
143
+ grid.add_column(style="dim", min_width=_LABEL_WIDTH)
144
+ grid.add_column()
145
+ grid.add_row("Repository", Text(str(status.repo_root), style="bold"))
146
+ grid.add_row("Commit", status.indexed_commit[:7] if status.indexed_commit else "no git commit")
147
+ grid.add_row("Built", status.indexed_at.strftime("%Y-%m-%d %H:%M UTC"))
148
+ grid.add_row("Status", _freshness(status))
149
+ return Panel(grid, title=_title("compass index"), border_style=GOLD, padding=(1, 2))
150
+
151
+
152
+ def _totals(result: OverviewResult) -> Table:
153
+ counts, calls = result.counts, result.call_resolution
154
+ percent = round(100 * calls.resolved / calls.total) if calls.total else 0
155
+
156
+ left = Table.grid(padding=(0, 3))
157
+ left.add_column(style="dim", min_width=_LABEL_WIDTH)
158
+ left.add_column(style="bold")
159
+ left.add_row("Files", f"{counts.files:,}")
160
+ left.add_row("Classes", f"{counts.classes:,}")
161
+ left.add_row("Functions", f"{counts.functions:,}")
162
+ resolved = Text(f"{percent}%", style="bold")
163
+ resolved.append(f" ({calls.resolved:,} of {calls.total:,})", style="dim")
164
+ left.add_row("Calls resolved", resolved)
165
+
166
+ right = Table.grid(padding=(0, 3))
167
+ right.add_column(style="dim", min_width=_LABEL_WIDTH)
168
+ right.add_column(style="bold")
169
+ for edge, count in counts.edges_by_type.items():
170
+ right.add_row(EDGE_LABELS[edge], f"{count:,}")
171
+
172
+ columns = Table.grid(padding=(0, 8))
173
+ columns.add_column()
174
+ columns.add_column()
175
+ columns.add_row(left, right)
176
+ return columns
177
+
178
+
179
+ def _ranked(ranked: tuple[RankedSymbol, ...], count_header: str) -> Table:
180
+ """One row per symbol with its count; files show only their path."""
181
+ if all(item.symbol.kind is SymbolKind.FILE for item in ranked):
182
+ files = _table("File", count_header, numeric=(count_header,))
183
+ for item in ranked:
184
+ files.add_row(_location(item.symbol), f"{item.count:,}")
185
+ return files
186
+ table = _table("Name", "Location", count_header, numeric=(count_header,))
187
+ for item in ranked:
188
+ table.add_row(_name(item.symbol), _location(item.symbol), f"{item.count:,}")
189
+ return table
190
+
191
+
192
+ def overview_view(result: OverviewResult) -> Group:
193
+ """The shape of the repository: totals, then one table per hot-spot list.
194
+
195
+ Args:
196
+ result: An overview result.
197
+
198
+ Returns:
199
+ The index line, a gold panel of totals, the entry points and the ranked tables,
200
+ then any caveats.
201
+
202
+ Example:
203
+ A panel with ``Files 147`` and ``Calls 225``, then ``Most called functions`` as a
204
+ table of ``Name``, ``Location`` and ``Callers``.
205
+ """
206
+ parts: list[RenderableType] = [
207
+ index_line(result.index),
208
+ Panel(_totals(result), title=_title("compass overview"), border_style=GOLD, padding=(1, 2)),
209
+ ]
210
+ if result.entry_points:
211
+ entries = _table("File", "Module")
212
+ for symbol in result.entry_points:
213
+ entries.add_row(_location(symbol), Text(symbol.qualified_name, style="dim"))
214
+ parts.append(_section("Entry points (files nothing imports)", entries))
215
+ sections = (
216
+ ("Most imported files", result.most_imported_files, "Importers"),
217
+ ("Most called functions", result.most_called_functions, "Callers"),
218
+ ("Riskiest to change", result.riskiest_to_change, "Affected"),
219
+ )
220
+ for title, ranked, header in sections:
221
+ if ranked:
222
+ parts.append(_section(title, _ranked(ranked, header)))
223
+ if result.top_external_libraries:
224
+ libraries = _table("Library", "Calls", numeric=("Calls",))
225
+ for lib in result.top_external_libraries:
226
+ libraries.add_row(Text(lib.library, style="bold"), f"{lib.call_count:,}")
227
+ parts.append(_section("Top external libraries", libraries))
228
+ parts += _caveats(result.caveats)
229
+ return Group(*parts)
230
+
231
+
232
+ def search_view(result: SearchResult) -> Group:
233
+ """Search hits as a table, best first, with why each matched.
234
+
235
+ Args:
236
+ result: A search result.
237
+
238
+ Returns:
239
+ The index line, a title with the hit count, the table and any caveats.
240
+
241
+ Example:
242
+ ``search "save" · 2 hits`` then rows like ``save method app/models.py:2 exact
243
+ name · 1 caller``.
244
+ """
245
+ table = _table("Name", "Kind", "Location", "Match")
246
+ for hit in result.hits:
247
+ table.add_row(
248
+ _name(hit.symbol),
249
+ Text(hit.symbol.kind.value, style="dim"),
250
+ _location(hit.symbol),
251
+ Text(match_reason(hit), style="dim"),
252
+ )
253
+ title = Text(f'search "{result.query}"', style=f"bold {GOLD}")
254
+ title.append(f" · {plural(result.total, 'hit')}", style="dim")
255
+ return Group(
256
+ index_line(result.index),
257
+ Text(""),
258
+ title,
259
+ table,
260
+ *_more(len(result.hits), result.total),
261
+ *_caveats(result.caveats),
262
+ )
263
+
264
+
265
+ def _neighbours(title: str, symbols: tuple[SymbolRef, ...]) -> list[RenderableType]:
266
+ if not symbols:
267
+ return []
268
+ table = _table("Name", "Kind", "Location")
269
+ for symbol in symbols:
270
+ table.add_row(_name(symbol), Text(symbol.kind.value, style="dim"), _location(symbol))
271
+ return [_section(f"{title} ({len(symbols)})", table)]
272
+
273
+
274
+ def describe_view(detail: NodeDetail, *, include_source: bool = False) -> Group:
275
+ """One symbol: a panel with where and what it is, then a table per neighbour list.
276
+
277
+ Args:
278
+ detail: A describe result.
279
+ include_source: Also show the symbol's source text.
280
+
281
+ Returns:
282
+ The index line, the symbol panel, the neighbour tables and any caveats.
283
+
284
+ Example:
285
+ A panel titled ``method User.save`` with ``Location app/models.py:6-7`` and
286
+ ``Id app/models.py::User.save``, then ``Callees (1)``.
287
+ """
288
+ symbol = detail.symbol
289
+ grid = Table.grid(padding=(0, 3))
290
+ grid.add_column(style="dim", min_width=_LABEL_WIDTH)
291
+ grid.add_column()
292
+ grid.add_row("Name", _name(symbol))
293
+ span = location(symbol)
294
+ if symbol.file_path and symbol.line_start and symbol.line_end != symbol.line_start:
295
+ span = f"{span}-{symbol.line_end}"
296
+ grid.add_row("Location", span)
297
+ grid.add_row("Id", Text(symbol.id, style="dim"))
298
+ if symbol.signature:
299
+ grid.add_row("Signature", Text(symbol.signature, style="bold"))
300
+ body: list[RenderableType] = [grid]
301
+ if detail.docstring:
302
+ body += [Text(""), Text(detail.docstring.strip(), style="italic")]
303
+ parts: list[RenderableType] = [
304
+ index_line(detail.index),
305
+ Panel(
306
+ Group(*body),
307
+ title=_title(f"{symbol.kind.value} {symbol.name}"),
308
+ border_style=GOLD,
309
+ padding=(1, 2),
310
+ ),
311
+ ]
312
+ parts += _neighbours("Bases", detail.bases)
313
+ parts += _neighbours("Subclasses", detail.subclasses)
314
+ parts += _neighbours("Members", detail.members)
315
+ parts += _neighbours("Callers", detail.callers)
316
+ parts += _neighbours("Callees", detail.callees)
317
+ parts += _neighbours("Imports", detail.imports)
318
+ parts += _neighbours("Imported by", detail.imported_by)
319
+ if detail.truncated:
320
+ parts.append(
321
+ Text("! some lists were cut short; describe the related symbols directly", "yellow")
322
+ )
323
+ if include_source and symbol.source:
324
+ parts.append(_section("Source", Text(symbol.source.rstrip())))
325
+ parts += _caveats(detail.caveats)
326
+ return Group(*parts)
327
+
328
+
329
+ def _impact_row(table: Table, item: ResultItem) -> None:
330
+ via = via_text(item.via) if item.via else ""
331
+ confidence = "" if item.min_confidence is None else f"{item.min_confidence:.2f}"
332
+ table.add_row(
333
+ str(item.distance),
334
+ _name(item.symbol),
335
+ _location(item.symbol),
336
+ Text(via, style="dim"),
337
+ confidence,
338
+ )
339
+
340
+
341
+ def impact_view(result: ImpactResult) -> Group:
342
+ """What may break if the target changes: a summary panel, then one row per symbol.
343
+
344
+ Args:
345
+ result: An impact result.
346
+
347
+ Returns:
348
+ The index line, the summary panel, the affected symbols nearest first and the
349
+ caveats (an empty answer is never shown as certain).
350
+
351
+ Example:
352
+ A panel ``impact of function decode_token`` with ``Affected 3 symbols in 2
353
+ files``, then rows like ``1 app.api.handle app/api.py:4 calls decode_token
354
+ 1.00``.
355
+ """
356
+ target = result.target
357
+ grid = Table.grid(padding=(0, 3))
358
+ grid.add_column(style="dim", min_width=_LABEL_WIDTH)
359
+ grid.add_column()
360
+ grid.add_row("Target", _name(target))
361
+ grid.add_row("Location", location(target))
362
+ grid.add_row("Depth", str(result.depth))
363
+ grid.add_row(
364
+ "Affected",
365
+ Text(
366
+ f"{plural(result.total, 'symbol')} in {plural(result.affected_file_count, 'file')}",
367
+ style="bold",
368
+ ),
369
+ )
370
+ table = _table("Hops", "Name", "Location", "Via", "Confidence", numeric=("Hops", "Confidence"))
371
+ shown = 0
372
+ for group in result.groups:
373
+ for item in group.items:
374
+ _impact_row(table, item)
375
+ shown += 1
376
+ parts: list[RenderableType] = [
377
+ index_line(result.index),
378
+ Panel(
379
+ grid,
380
+ title=_title(f"impact of {target.kind.value} {target.name}"),
381
+ border_style=GOLD,
382
+ padding=(1, 2),
383
+ ),
384
+ ]
385
+ if shown:
386
+ parts.append(table)
387
+ parts += _more(shown, result.total)
388
+ parts += _caveats(result.caveats)
389
+ return Group(*parts)
compass_cli/types.py ADDED
@@ -0,0 +1,41 @@
1
+ """Typed data objects shared across compass_cli commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from enum import StrEnum
7
+ from pathlib import Path
8
+
9
+ from compass_core.shared_types import Language
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class IngestSummary:
14
+ """Aggregate results of a single `compass ingest` run."""
15
+
16
+ file_count: int
17
+ class_count: int
18
+ function_count: int
19
+ elapsed: float
20
+ node_count: int
21
+ edge_count: int
22
+ db_path: Path
23
+ db_size: int
24
+ skipped: int
25
+ resolved_pct: float
26
+ orphan_count: int
27
+ language_counts: dict[Language, int]
28
+ dropped_edges: int = 0
29
+
30
+
31
+ class OutputFormat(StrEnum):
32
+ """How a query command prints its answer.
33
+
34
+ Attributes:
35
+ TEXT: Compact text, one line per item with ``file:line`` first; for people and
36
+ coding agents.
37
+ JSON: The typed contract result as JSON; for scripts and tools.
38
+ """
39
+
40
+ TEXT = "text"
41
+ JSON = "json"
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.5
2
+ Name: compass-code
3
+ Version: 0.1.0
4
+ Summary: Local-first code knowledge graph for AI coding agents: the compass command and its MCP server.
5
+ Project-URL: Homepage, https://github.com/NIKU-SINGH/code-compass
6
+ Project-URL: Repository, https://github.com/NIKU-SINGH/code-compass
7
+ Project-URL: Issues, https://github.com/NIKU-SINGH/code-compass/issues
8
+ License-Expression: Apache-2.0
9
+ Keywords: code-graph,coding-agents,knowledge-graph,mcp,tree-sitter
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Topic :: Software Development
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: fastapi>=0.115.0
19
+ Requires-Dist: mcp<2,>=1.26.0
20
+ Requires-Dist: pathspec>=1.0.4
21
+ Requires-Dist: pydantic-settings>=2.0.0
22
+ Requires-Dist: pydantic>=2.0.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+ Requires-Dist: real-ladybug<0.16,>=0.15.3
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: tree-sitter-python<0.26,>=0.25.0
27
+ Requires-Dist: tree-sitter<0.26,>=0.25.0
28
+ Requires-Dist: typer>=0.9.0
29
+ Requires-Dist: uvicorn>=0.32.0
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Code Compass
33
+
34
+ **A local-first code knowledge graph for AI coding agents.** Code Compass parses your
35
+ repository with Tree-sitter into a graph of files, classes, functions and the calls,
36
+ imports and inheritance between them, and answers structural questions from it: where
37
+ something is defined, who calls it, and what may break if it changes. Coding agents
38
+ (Claude Code, Codex, Cursor) ask over MCP; you ask with the `compass` command or in a 3D
39
+ web view. Parsing is deterministic and nothing leaves your machine: no API keys, no
40
+ embeddings, no network calls.
41
+
42
+ > **Alpha.** Python repositories only; call resolution is partial, and every answer says
43
+ > where it may be incomplete.
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ uv tool install compass-code # or: pipx install compass-code
49
+ ```
50
+
51
+ ## Use
52
+
53
+ ```bash
54
+ cd your-repo
55
+ compass ingest . # build the graph in .compass/
56
+ compass overview # entry points and hot spots
57
+ compass search save # where is it defined?
58
+ compass describe app/models.py::User
59
+ compass impact decode_token # what may break if it changes?
60
+ compass serve # explore the graph in the browser
61
+ compass setup --mcp # let coding agents in this repo use it
62
+ ```
63
+
64
+ For Codex, add to `~/.codex/config.toml`:
65
+
66
+ ```toml
67
+ [mcp_servers.code-compass]
68
+ command = "compass"
69
+ args = ["mcp"]
70
+ ```
71
+
72
+ Documentation, source and issues: https://github.com/NIKU-SINGH/code-compass
@@ -0,0 +1,137 @@
1
+ compass_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ compass_cli/display.py,sha256=krgkeDQuT8iIAIW_QLpufCPo6H-aI2P8wE79ey3aEPY,8043
3
+ compass_cli/errors.py,sha256=PYXZuU2uoYTTO1kje_Iip3h6cOU9Bzd8iCo165vO-yY,809
4
+ compass_cli/main.py,sha256=e_PefCx8nl9y09ri0gmfUKVixQq05M2VZtroODiBjfo,1497
5
+ compass_cli/progress.py,sha256=ZK9DaK7iD-dgindMKK15kmPySSE-HuNAF0uDtokE8sI,6487
6
+ compass_cli/result_views.py,sha256=NiCB7hhUkzZsus7ey2hua9RkX1psRWd6cZg36NfhCcs,14013
7
+ compass_cli/types.py,sha256=mWVTx5R-yx1LMn8VOgWrYmxsOPOrasWTMbdEunlOEcQ,955
8
+ compass_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ compass_cli/commands/ingest.py,sha256=I7ejSqfBb_bRqK9Gd5u-e-wo5ZRdt8L6d51llYQKFaE,12237
10
+ compass_cli/commands/mcp.py,sha256=CBH8t-rx3l7-XR9oYi_5n0jVAmUOnOVqEC3_Zbu4pmM,693
11
+ compass_cli/commands/query.py,sha256=zNkD-nEsv5mQGyjm_2rGu41vr5zljograpmR7JtFCOU,7255
12
+ compass_cli/commands/serve.py,sha256=5lQKA-yG7XoQlCPS7yEj5Z8bFXfZIOVaC_PjCEvdGUs,4199
13
+ compass_cli/commands/setup.py,sha256=xtcmauTOE716zPA3OARLzvnkRMTrR77GDa5IjwHfSro,5836
14
+ compass_core/__init__.py,sha256=bLZ28IvgwA7oBuxlzvElrUyjSnFyRiiAViXnU0mAnR4,36
15
+ compass_core/errors.py,sha256=inwih-HI_0lHP61sW4QS6QzL6YUO40iV6xjTeC3-658,4640
16
+ compass_core/logger.py,sha256=KErtsdB0Ns8Jng8sGw5SrwB751ynY0OmYn34uw61yZM,1209
17
+ compass_core/progress.py,sha256=Xt74PchS_Ryq8TM2UZlzktHrTAO1LkXlqXiiCpnIpZI,1274
18
+ compass_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ compass_core/render.py,sha256=z_qzdxdCLMYLZaU5tAidZKJmRFtseQiaG90_Z1BtctI,13213
20
+ compass_core/settings.py,sha256=cWrkcniccwCKPgaLA9-f7-QPPFsGUItPSHSwrH2LMPA,2121
21
+ compass_core/shared_types.py,sha256=svqlJnMxXZy14woxHCSB7zDq27oTcujWV87tdM_11Xo,2340
22
+ compass_core/contract/__init__.py,sha256=OGDPIc8G_WnNzBWaWcVYvXWBlziYPfK3iE670SjiFZo,322
23
+ compass_core/contract/errors.py,sha256=ypaw7Y_EYM48PdsNTQA97RWkdk91a0CEY2Ang7LaSLY,3864
24
+ compass_core/contract/models.py,sha256=AjOreXm8OlBVEw2OnOBXjdAOs95grcW0PoGHnD27wGk,7478
25
+ compass_core/contract/params.py,sha256=8US4THZ46ukORVI3IjeFsGZCU0VE7BRWTS4gzN4MQ-E,3018
26
+ compass_core/contract/results.py,sha256=_2yIxn68Eyppoxcq3kJWNHJEeMbTddcFA7uwgv7QgfE,11245
27
+ compass_core/contract/serialize.py,sha256=mrPoYUUpYT7_gyETdmRwzIh_H4FdXGJh9QXVChKfcLE,1507
28
+ compass_core/contract/types.py,sha256=d8TqDwb4jDjJNhrjECXUoLabKdEpkLgLY--5EcAxm6I,2100
29
+ compass_core/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ compass_core/graph/db.py,sha256=Wx1znvYeKC87qFzRCqFVaznZ_DyiSbTbfllhmAjyLS4,7469
31
+ compass_core/graph/schema.py,sha256=5sCkUFpQpSWyLzGrg0TuBYqlq8I2RawUyVM9zfh4uPY,6152
32
+ compass_core/graph/stored_ids.py,sha256=p1MPMXcFjDW8vsvO4G4ojKx5MstvWk9ICvRmJHV6rGI,4567
33
+ compass_core/graph/writer.py,sha256=1CynWY_EJE27ioDM-BsrAJ-sNjl6Pz6ujR3NMr9gx-w,17721
34
+ compass_core/index/__init__.py,sha256=pznUFyoF9HfB5GurNvgW6MBNzS1zfvyS-Wpln54g__Q,57
35
+ compass_core/index/freshness.py,sha256=FiMgyNJRa1Hyw_1OSznsB-d-E59qlaysaU7u8mDutvo,1868
36
+ compass_core/index/locate.py,sha256=YSJPFVKA-OwlccaWy98jmt0ZVXIdxAV6wmIeZuNDA5M,4957
37
+ compass_core/index/metadata.py,sha256=3kfBx1UTmmEusnZFMvER91bZmRiLhaqr4rVh10o3m4Q,4162
38
+ compass_core/ir/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ compass_core/ir/graph.py,sha256=ItJHo16U24EQnbHGJrTB41RN0BuGJv4fJisMqKOgt30,1753
40
+ compass_core/ir/models.py,sha256=36Lf4OlGbROWbRpoCAcmKvphhF5g8KWIUwDkYtPJKsM,2075
41
+ compass_core/languages/__init__.py,sha256=U5_wQ2gIBTys9lGpzlNNCvIjgLsnvzBpZ2DYx_30NnY,67
42
+ compass_core/languages/base.py,sha256=BtR8X4LCXW177kPPInokBip06DEXjN72EUR3LMjFz20,721
43
+ compass_core/languages/registry.py,sha256=rGk0fsBsS-LWoUHEbN1T_kOJajhMN7AhbahvmkvkjsY,3114
44
+ compass_core/languages/python/__init__.py,sha256=_zIlp3tJ-ivgZr6lCt9MJ5YVBwvq40a0OsThL0zRjJQ,297
45
+ compass_core/languages/python/extractor.py,sha256=wsqlP9r3zNysviqs3ls523VHRzjjCTIumh_hJzOnJuE,24802
46
+ compass_core/languages/python/import_resolver.py,sha256=s0SHp-dcnHmNYl1qo2TdPuqtD3htbiBWXjFNALZ2T4U,4485
47
+ compass_core/phases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ compass_core/phases/base.py,sha256=OEC5TQHKZBu6v8huJPky8H7QdP7e90W64GtM914z-sQ,1593
49
+ compass_core/phases/discovery.py,sha256=UcgZnYt5ttlLkHwOlD2vF_Uq62Wh6ibl4abuHYxkmQQ,5454
50
+ compass_core/phases/parse.py,sha256=PAJiEoUB48hJrsZRNFnYU6UUcDkoEwvzKK-kMGUyB7Y,3052
51
+ compass_core/phases/persistence.py,sha256=Bw5mNh6YaOh0qgMJUFvg8CeJ8d0XCH5YqLebXa458-4,1327
52
+ compass_core/phases/pipeline.py,sha256=iSpinvT_QUOe2XhJIgbUC1QLHhblh06NI8aFlSwcc1s,5508
53
+ compass_core/phases/resolution.py,sha256=ifE-PPTted4HvKcUt9EY7vXz0db281DKUzZn2-HWaVQ,23199
54
+ compass_core/phases/symbol_table.py,sha256=sHRuNFY70mgwIMSe6FgIDG_CSzqbE21AWyAxrh_Kjy0,1389
55
+ compass_core/phases/validation.py,sha256=VPSrzXLdCry0hO5Z_VGrjDCN5dPmPPJb_uElXVfHIQc,2869
56
+ compass_core/query/__init__.py,sha256=Ht8JXVvajtbujwCJMsPCbTh5yP6GEficDsFsuCCkMpI,66
57
+ compass_core/query/cypher.py,sha256=B0i6xB5e18PIy5ewbseCN7vqtmQqkWgYV_0gwcin4BU,3602
58
+ compass_core/query/detail.py,sha256=sUyX_jVpiWFmJs5UsykgNQJjZjRz8Dj4yKShOzLeESA,8804
59
+ compass_core/query/graph_map.py,sha256=RIX_I9JhL55v2QNUrWCNuSYmTx04xRs9_iz4CB3_JM8,4116
60
+ compass_core/query/impact.py,sha256=piSg_4h_GkquUgAnA65X2sGfWpMonzR2GuhlL6FVP4E,11472
61
+ compass_core/query/impact_walk.py,sha256=5wXP80ocsbYCYFND7nWnzerELHokEJdhWzHBxU9Kk6k,14703
62
+ compass_core/query/overview.py,sha256=IZNxaOLXfmT2--WYrryixLzKjvRbtOxaU-EPm34kh6c,8474
63
+ compass_core/query/references.py,sha256=lcHFl2nx71PKwWJUQ5zVTtVNqzvbMqjjOyOpXbGnwEQ,8941
64
+ compass_core/query/rows.py,sha256=Ar-PJdpVBiBrYoYA1RSCK3ZXKZRSPsq_quJqsT9X0t4,11752
65
+ compass_core/query/search.py,sha256=QAaUIKneWu51ZNyxGyuKvRDixPkR8UBEjoTmpYPpbJA,6950
66
+ compass_core/query/status.py,sha256=c7eb204_nB3zjkBs5SeIfRSiCkC6Wi1k86vS1hGW5ws,1757
67
+ compass_core/query/walk_queries.py,sha256=Rvkla5pb1Nm5gyva745fwqauIMcM21Cg-uO7CX-XyJc,5911
68
+ compass_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
+ compass_mcp/guide.py,sha256=rAYwnxn0TZypSyDPxRdYorQ2OMPbtc_lNNIFt7CuqmM,2450
70
+ compass_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ compass_mcp/server.py,sha256=-owv7sHphYh8_VW3yUa_HZRz2JxpGC77PTo3UakR_jc,10015
72
+ compass_server/__init__.py,sha256=uVqAZBP4QElVBIzkwhNYC4qJYp6NKm4p3wtOss66zdM,209
73
+ compass_server/errors.py,sha256=rz8nCLlSo8miCsQeTRREZ7s_oPBiC3Ag4xm8aur5b0s,2959
74
+ compass_server/main.py,sha256=O9K6bznDv2QvBgWTSrnjqLwRoVRyBG9-AR8KjuJWE1M,1437
75
+ compass_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
+ compass_server/settings.py,sha256=GFgJTRK7Y0icLKgg53FyUlbILki101yuHC4ISZZbYhc,1543
77
+ compass_server/web_bundle.py,sha256=_miKsqgubeU_Swcx8Vg5GPLivVj_H-ZGaY_fkVtQ8tk,840
78
+ compass_server/web_limits.py,sha256=gmGP8CnpOouCNFSf2yfNJWsIKIZpRUaxG_JWK4j1LOY,1640
79
+ compass_server/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
+ compass_server/routers/query.py,sha256=mnhBBHYFjR-Lu-72Xi3lDcpVQjFar4MWWkz9ei_nRr4,6498
81
+ compass_server/static/404.html,sha256=xx5ek8k-8rmKLQY2mWnjQoOTTrO6cF6CY6Z__OFTMcU,8944
82
+ compass_server/static/index.html,sha256=0pNeobPgYfp1_7NoA8fipDvsgj5cUinRw9hrE-2EaTw,8837
83
+ compass_server/static/index.txt,sha256=TSPr0oaUdavPv7hF4tR0-AE7OJp_oP7TCuk4vNcjlN8,4917
84
+ compass_server/static/_next/static/chunks/1629039a.eed2a06658ec4f9c.js,sha256=CzwYPfFrw8P8JQYIqRjPOoUI9bjjsMGeJkhTQ72wYP8,325287
85
+ compass_server/static/_next/static/chunks/1ff282bf-bb7c483245264fc9.js,sha256=v36UjjYs-FTFbnbFaCOG9X8vjZIcmnDYxcFgd131cVw,173024
86
+ compass_server/static/_next/static/chunks/223.f881a22f446259bf.js,sha256=0B72j0iI_J2ksjZAXKJzQ0frU3TU3I6RIBPwRxfEOPQ,242122
87
+ compass_server/static/_next/static/chunks/51fa5c19.6396973222c9d6fd.js,sha256=LlR323CG2bbBFD7DKcoYEn-naLLHnZtlT8sQGPTouHU,615887
88
+ compass_server/static/_next/static/chunks/556.443c1682b6b20128.js,sha256=E01B1nCUGSXk6R5ufcxHON27xsaii-UP-Tej2btlN4Y,12512
89
+ compass_server/static/_next/static/chunks/684-1aa0170f59baf77e.js,sha256=fGIZoOayzSCMeA1LZ2yebfA1oSREDXNXVk885_GbxLY,643162
90
+ compass_server/static/_next/static/chunks/92e71660.3a42d4f70d017951.js,sha256=pApYdSv8vU-m31VwFmj-8jJAZDwh3n2tQw2wH0igQ90,356819
91
+ compass_server/static/_next/static/chunks/937-8692224bb6d1b605.js,sha256=fdiJJPvd7INYsAJKoJ7o04txhGNdAEOM2zhxUOgLUWQ,173207
92
+ compass_server/static/_next/static/chunks/framework-96dcd958cfe08bd4.js,sha256=aVpaPpZV0_FPiahM-SI4Mgj8toXHGxlCOP-ThrWHAxA,189785
93
+ compass_server/static/_next/static/chunks/main-6dee8e626b16731a.js,sha256=--C4B4IYTh1m6Ju77MDPdyvxeIVSmny7lfMPGKmRfu8,127924
94
+ compass_server/static/_next/static/chunks/main-app-460e8bc670818718.js,sha256=-zXnZGz9DsQnVjxS51Xp4SQ9J0QWNf_sc41Gm1fuyTY,569
95
+ compass_server/static/_next/static/chunks/polyfills-42372ed130431b0a.js,sha256=CXPB1kyIrcjjyVBBDLWLKI9yEY1ZZbeASUON648vloM,112594
96
+ compass_server/static/_next/static/chunks/webpack-597057bf48ce4111.js,sha256=8fUZdRdxkSDbh4vowE-E9L3fyJ-tC1IaX_snJzLOevk,3713
97
+ compass_server/static/_next/static/chunks/app/layout-4bd0ba4a7d18aff9.js,sha256=xIYQqZKBs1Se2ByHaVevd4895_8Ki2QiZ4LGpZb2i20,991
98
+ compass_server/static/_next/static/chunks/app/page-5376a0a98bbd1faa.js,sha256=4iwaIvueAxRBjxc96iLPeyS8PPB4Uxg-yp0Pw0ryBxo,91866
99
+ compass_server/static/_next/static/chunks/app/_not-found/page-2c96ddf295eb6a86.js,sha256=53bragw1qG3uwojbLK45JWTExwp3pgofBhuZpgHWNJY,2680
100
+ compass_server/static/_next/static/chunks/pages/_app-638a3e7363f92b80.js,sha256=J0xoqYN9AaBB2ZCzKOERq1xoejbtN95S046ubjJNCuQ,239
101
+ compass_server/static/_next/static/chunks/pages/_error-6a72dbbb45cae743.js,sha256=oVBW5enTs3OVGsSJZ5_Sh7ItTkD2qaKyn60urQFjDxc,221
102
+ compass_server/static/_next/static/css/1b0fbfd8dd653f37.css,sha256=6VPo2Lz-UXQ8iAAiUxTF2-gXWOxB0R1DKUKnjkj4joM,77188
103
+ compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_buildManifest.js,sha256=JL8CFWQG0GDopX39z0HQhfbSBn_QYSeaxQAoXOEcBLk,506
104
+ compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
105
+ compass_server/static/_next/static/media/0086f8992871c45b-s.woff2,sha256=ZuG4x8ScKDWJ7JAWdL_zaIujYyDK1MKe6cz00Do6KCA,21252
106
+ compass_server/static/_next/static/media/034d78ad42e9620c-s.woff2,sha256=I2F6G_Zn3Wop4nJKxlledZJFSdHCXoZy4jRu84vJmEo,39504
107
+ compass_server/static/_next/static/media/03b436aa846269de-s.woff2,sha256=0NNYz8z88OMGB9ig3HrOCAkIfzONfx80okR94Nqqw3U,23588
108
+ compass_server/static/_next/static/media/0484562807a97172-s.p.woff2,sha256=hy6GKRhZGp6CTcA-2S8FcpQ1_7uOu7EO_37aJlkrF5g,7992
109
+ compass_server/static/_next/static/media/08aedeceaf1dcd57-s.woff2,sha256=VWBvvHbcIyxb6471hNe09_duManyeHcRLnVIQ1ZGJ4E,20176
110
+ compass_server/static/_next/static/media/0aa834ed78bf6d07-s.woff2,sha256=r3SGlViAvhwrly6cdmrP-3dnaNZptldu2aCRnOcufKY,12064
111
+ compass_server/static/_next/static/media/29a4aea02fdee119-s.woff2,sha256=briALXMZ_NSIUOs45B7W6hLZF_qv36x9rlYUpRfcK1Q,39204
112
+ compass_server/static/_next/static/media/29e7bbdce9332268-s.woff2,sha256=bY70Ir5NgnA39vLVdmoICAGIdvpemqmpJ4f62dHxeTg,39384
113
+ compass_server/static/_next/static/media/36008747766f78c6-s.woff2,sha256=Nn317QKwguP62WFcVPVqorU4gzElessivmDHwKYI5kc,17280
114
+ compass_server/static/_next/static/media/39969fcf98a3026e-s.woff2,sha256=eOhQ1WmDSJLT9L39IITHp8DcZK5CJvMjGvMNrnBkAOI,3028
115
+ compass_server/static/_next/static/media/4de1fea1a954a5b6-s.p.woff2,sha256=1K5RiKZTcOz-KPQik7vugpfP1XEsaq39snDUjyvNiLA,13980
116
+ compass_server/static/_next/static/media/5c0c2bcbaa4149ca-s.p.woff2,sha256=axAqs1qh8rMVeIu0hTQ07R5SE3YDv3o9pxpoInZ0jUU,37792
117
+ compass_server/static/_next/static/media/67957d42bae0796d-s.woff2,sha256=Pt82Pb-dX6DNx4SuK0MaikFS9AVaiohYAowL1miAgnM,9084
118
+ compass_server/static/_next/static/media/6d38f9d4e0f4772b-s.woff2,sha256=qRSdr4LKX-8cEr3uSSdJ9JPC4uQxN2py-58DXmcGRXM,8908
119
+ compass_server/static/_next/static/media/6d664cce900333ee-s.p.woff2,sha256=enzho08-mUT-iPxhq7yTtts4OvorkIFf18zqRW-85OU,14168
120
+ compass_server/static/_next/static/media/886030b0b59bc5a7-s.woff2,sha256=mS7qL3AhBFfd0Rlt5N8yQJGf_gaK0YjHnZhfukVl078,2020
121
+ compass_server/static/_next/static/media/8888a3826f4a3af4-s.p.woff2,sha256=KJ4K_IvnMahoIjSeVFVylvFFkmSWvSE42xusDbd_d6I,7740
122
+ compass_server/static/_next/static/media/939c4f875ee75fbb-s.woff2,sha256=fbev-84f3uacH_wmQbvKKJsEmGf1JMnYYf41q2Zwvyk,15204
123
+ compass_server/static/_next/static/media/a1386beebedccca4-s.woff2,sha256=JHdoOksSAGgHgKdZzBuTuBZBA2LcX0x06_6vohK8t00,5448
124
+ compass_server/static/_next/static/media/ab00a911ac2adf48-s.woff2,sha256=j9lctmxT1fJjcHurU2RDdFb_wtW7eA56zobNVtWBgj4,29236
125
+ compass_server/static/_next/static/media/b957ea75a84b6ea7-s.p.woff2,sha256=GXo8vXKQwkLFx2UmjN1pqaOYZ_3IDNEwcfJDqBxW-3Y,7848
126
+ compass_server/static/_next/static/media/bb3ef058b751a6ad-s.p.woff2,sha256=HgZ0CgKkQ_t_Pu2o_KpoWg9sYg4_AeZmboRylUac460,40480
127
+ compass_server/static/_next/static/media/c3bc380753a8436c-s.woff2,sha256=cu_Goyz9N8VXEIYoz_oBFTxIDD1M3lVnREBuULnY6fc,5552
128
+ compass_server/static/_next/static/media/cce080f35d014443-s.woff2,sha256=uFyExlW8u6O9YossH-oPvbWxWKkCIoGi-RDoL9baUJg,2988
129
+ compass_server/static/_next/static/media/db911767852bc875-s.woff2,sha256=nIxH7grqotN49OXVcZ7L8FpgGjXChdDUi4iBBrsVz0k,39160
130
+ compass_server/static/_next/static/media/eafabf029ad39a43-s.p.woff2,sha256=PcXQxSQo_haWJkkHoQVOu6rAf4y-RYMsEF-BnCrjl8A,7900
131
+ compass_server/static/_next/static/media/f10b8e9d91f3edcb-s.woff2,sha256=-PDChmHIjtvO4CKkqAZXYZ6JMa-MKkfCjiMDB-KvMOU,5496
132
+ compass_server/static/_next/static/media/f911b923c6adde36-s.woff2,sha256=E5DobMKCPnWTWJGMAcT8wbbk8BvKkVvb621o61wkRAU,7468
133
+ compass_server/static/_next/static/media/fe0777f1195381cb-s.woff2,sha256=H65ec9J4juHeodduyjqfFXoDht5r6MKA0HalOmTDWKE,5640
134
+ compass_code-0.1.0.dist-info/METADATA,sha256=2ZzAwOOZfZkM2LEhqJAme5blg3cu_v8pzcHGk3tKKCw,2694
135
+ compass_code-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
136
+ compass_code-0.1.0.dist-info/entry_points.txt,sha256=tY_5a4mMnxtpCok7wP4zOHzpuKTJoaKsNL9LGOot9fs,49
137
+ compass_code-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ compass = compass_cli.main:app
@@ -0,0 +1 @@
1
+ """Code Compass – core engine."""
@@ -0,0 +1,6 @@
1
+ """Public contract of the query engine: the types every adapter sends and receives.
2
+
3
+ Plain frozen dataclasses and enums with no database, I/O or adapter imports. The
4
+ query layer builds these values; the CLI, the MCP server and the HTTP server consume
5
+ them. Only ``serialize.py`` uses Pydantic, to turn them into JSON.
6
+ """