batho 0.1.4__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 (184) hide show
  1. batho/__init__.py +55 -0
  2. batho/bridge/__init__.py +42 -0
  3. batho/bridge/artifact_loader.py +214 -0
  4. batho/bridge/constants.py +79 -0
  5. batho/bridge/http_api.py +383 -0
  6. batho/bridge/mcp_server.py +159 -0
  7. batho/bridge/models.py +102 -0
  8. batho/bridge/registry_client.py +221 -0
  9. batho/bsg/__init__.py +31 -0
  10. batho/bsg/plugins/foundation/bsg_detection_cicd.yaml +87 -0
  11. batho/bsg/plugins/foundation/bsg_detection_cloud_providers.yaml +100 -0
  12. batho/bsg/plugins/foundation/bsg_detection_cpp.yaml +110 -0
  13. batho/bsg/plugins/foundation/bsg_detection_csharp.yaml +130 -0
  14. batho/bsg/plugins/foundation/bsg_detection_dart.yaml +89 -0
  15. batho/bsg/plugins/foundation/bsg_detection_elixir.yaml +92 -0
  16. batho/bsg/plugins/foundation/bsg_detection_foundation.yaml +268 -0
  17. batho/bsg/plugins/foundation/bsg_detection_kotlin.yaml +79 -0
  18. batho/bsg/plugins/foundation/bsg_detection_php.yaml +135 -0
  19. batho/bsg/plugins/foundation/bsg_detection_ruby.yaml +100 -0
  20. batho/bsg/plugins/foundation/bsg_detection_scala.yaml +93 -0
  21. batho/bsg/plugins/foundation/bsg_detection_swift.yaml +119 -0
  22. batho/bsg/plugins/foundation/bsg_detection_test_frameworks.yaml +130 -0
  23. batho/bsg/plugins/foundation/bsg_file_categorization.yaml +320 -0
  24. batho/bsg/plugins/foundation/bsg_framework_angular.yaml +40 -0
  25. batho/bsg/plugins/foundation/bsg_framework_django.yaml +44 -0
  26. batho/bsg/plugins/foundation/bsg_framework_flask.yaml +44 -0
  27. batho/bsg/plugins/foundation/bsg_framework_nodejs.yaml +378 -0
  28. batho/bsg/plugins/foundation/bsg_framework_other.yaml +278 -0
  29. batho/bsg/plugins/foundation/bsg_framework_python.yaml +249 -0
  30. batho/bsg/plugins/foundation/bsg_framework_react.yaml +92 -0
  31. batho/bsg/plugins/foundation/bsg_framework_vue.yaml +58 -0
  32. batho/bsg/plugins/foundation/bsg_graph_foundation.yaml +109 -0
  33. batho/bsg/plugins/foundation/bsg_token_optimization.yaml +184 -0
  34. batho/bsg/plugins/interceptors/bsg_api_contract_guardian.yaml +27 -0
  35. batho/bsg/plugins/interceptors/bsg_auth_boundary_shield.yaml +29 -0
  36. batho/bsg/plugins/interceptors/bsg_dependency_blast_radius.yaml +28 -0
  37. batho/bsg/plugins/interceptors/bsg_hardcoded_secret_catcher.yaml +30 -0
  38. batho/bsg/plugins/interceptors/bsg_iac_drift_sentinel.yaml +29 -0
  39. batho/bsg/plugins/interceptors/bsg_nplus1_query_catcher.yaml +29 -0
  40. batho/bsg/plugins/interceptors/bsg_resource_leak_preventer.yaml +27 -0
  41. batho/bsg/plugins/interceptors/bsg_schema_migration_enforcer.yaml +23 -0
  42. batho/bsg/plugins/interceptors/bsg_silent_failure_catcher.yaml +23 -0
  43. batho/bsg/plugins_cli.py +263 -0
  44. batho/bsg/rules.py +3268 -0
  45. batho/bsg/schemas/bsg-plugin-schema-v1.json +429 -0
  46. batho/bsg/testing.py +519 -0
  47. batho/cli/bridge.py +295 -0
  48. batho/cli/dashboard.py +280 -0
  49. batho/cloud_sync/__init__.py +11 -0
  50. batho/cloud_sync/client.py +358 -0
  51. batho/cloud_sync/config.py +55 -0
  52. batho/cloud_sync/uploader.py +195 -0
  53. batho/config.py +1021 -0
  54. batho/context/__init__.py +22 -0
  55. batho/context/bsg.py +8 -0
  56. batho/context/bsg_map.py +1835 -0
  57. batho/context/cache.py +473 -0
  58. batho/context/codegraph.py +1179 -0
  59. batho/context/extractor.py +1004 -0
  60. batho/context/graph_cache.py +99 -0
  61. batho/context/incremental.py +198 -0
  62. batho/context/languages/__init__.py +148 -0
  63. batho/context/languages/_common.py +271 -0
  64. batho/context/languages/bash.py +72 -0
  65. batho/context/languages/c.py +61 -0
  66. batho/context/languages/cpp.py +87 -0
  67. batho/context/languages/csharp.py +86 -0
  68. batho/context/languages/css.py +242 -0
  69. batho/context/languages/dart.py +84 -0
  70. batho/context/languages/detector.py +578 -0
  71. batho/context/languages/erlang.py +76 -0
  72. batho/context/languages/factory.py +500 -0
  73. batho/context/languages/go.py +67 -0
  74. batho/context/languages/hack.py +83 -0
  75. batho/context/languages/haskell.py +87 -0
  76. batho/context/languages/hcl.py +357 -0
  77. batho/context/languages/html.py +225 -0
  78. batho/context/languages/java.py +69 -0
  79. batho/context/languages/javascript.py +78 -0
  80. batho/context/languages/json.py +243 -0
  81. batho/context/languages/julia.py +83 -0
  82. batho/context/languages/kotlin.py +76 -0
  83. batho/context/languages/lua.py +70 -0
  84. batho/context/languages/markdown.py +357 -0
  85. batho/context/languages/objectivec.py +107 -0
  86. batho/context/languages/ocaml.py +87 -0
  87. batho/context/languages/perl.py +75 -0
  88. batho/context/languages/php.py +74 -0
  89. batho/context/languages/python.py +106 -0
  90. batho/context/languages/r.py +63 -0
  91. batho/context/languages/registry.py +635 -0
  92. batho/context/languages/ruby.py +67 -0
  93. batho/context/languages/rust.py +75 -0
  94. batho/context/languages/scala.py +99 -0
  95. batho/context/languages/swift.py +94 -0
  96. batho/context/languages/toml.py +262 -0
  97. batho/context/languages/typescript.py +88 -0
  98. batho/context/languages/verilog.py +100 -0
  99. batho/context/languages/yaml.py +285 -0
  100. batho/context/languages/zig.py +88 -0
  101. batho/context/mmap_storage.py +63 -0
  102. batho/context/pipeline.py +381 -0
  103. batho/context/query.py +313 -0
  104. batho/context/schema.py +227 -0
  105. batho/context/storage.py +1727 -0
  106. batho/context/symbol_index.py +124 -0
  107. batho/dashboard/DESIGN.md +8 -0
  108. batho/dashboard/README.md +51 -0
  109. batho/dashboard/assets/css/animations.css +35 -0
  110. batho/dashboard/assets/css/base.css +139 -0
  111. batho/dashboard/assets/css/components.css +326 -0
  112. batho/dashboard/assets/css/graph.css +267 -0
  113. batho/dashboard/assets/css/tokens.css +119 -0
  114. batho/dashboard/assets/fonts/inter-500.woff2 +11 -0
  115. batho/dashboard/assets/fonts/inter-500.woff2.LICENSE +2 -0
  116. batho/dashboard/assets/fonts/inter-600.woff2 +11 -0
  117. batho/dashboard/assets/fonts/space-grotesk-500.woff2 +11 -0
  118. batho/dashboard/assets/fonts/space-grotesk-500.woff2.LICENSE +2 -0
  119. batho/dashboard/assets/fonts/space-grotesk-700.woff2 +11 -0
  120. batho/dashboard/assets/js/ctn-loader.js +424 -0
  121. batho/dashboard/assets/js/cy-import.js +34 -0
  122. batho/dashboard/assets/js/cy-stylesheet.js +156 -0
  123. batho/dashboard/assets/js/format.js +60 -0
  124. batho/dashboard/assets/js/glob.js +94 -0
  125. batho/dashboard/assets/js/graph-stream.js +158 -0
  126. batho/dashboard/assets/js/main.js +175 -0
  127. batho/dashboard/assets/js/router.js +101 -0
  128. batho/dashboard/assets/js/store.js +53 -0
  129. batho/dashboard/index.html +88 -0
  130. batho/dashboard/pages/files.js +275 -0
  131. batho/dashboard/pages/hypergraph.js +564 -0
  132. batho/dashboard/pages/metrics.js +6 -0
  133. batho/dashboard/pages/overview.js +752 -0
  134. batho/dashboard/pages/relationships.js +192 -0
  135. batho/dashboard/pages/rules.js +6 -0
  136. batho/dashboard/pages/search.js +6 -0
  137. batho/dashboard/pages/snapshots.js +234 -0
  138. batho/dashboard/shared/components/audit-export.js +127 -0
  139. batho/dashboard/shared/components/chip-filter.js +67 -0
  140. batho/dashboard/shared/components/code-pane.js +47 -0
  141. batho/dashboard/shared/components/data-table.js +206 -0
  142. batho/dashboard/shared/components/drawer.js +134 -0
  143. batho/dashboard/shared/components/entity-chip.js +75 -0
  144. batho/dashboard/shared/components/header-bar.js +230 -0
  145. batho/dashboard/shared/components/kpi-row.js +28 -0
  146. batho/dashboard/shared/components/latency-bar.js +69 -0
  147. batho/dashboard/shared/components/side-rail.js +73 -0
  148. batho/dashboard/shared/components/staleness-gauge.js +69 -0
  149. batho/dashboard/shared/components/stat-tile.js +41 -0
  150. batho/dashboard/shared/components/tab-bar.js +70 -0
  151. batho/dashboard/vendor/cytoscape/LICENSE +19 -0
  152. batho/dashboard/vendor/cytoscape/VERSION.txt +1 -0
  153. batho/dashboard/vendor/cytoscape/cytoscape.min.js +32 -0
  154. batho/dashboard/vendor/marked/LICENSE +1 -0
  155. batho/dashboard/vendor/marked/VERSION.txt +1 -0
  156. batho/dashboard/vendor/marked/marked.min.js +6 -0
  157. batho/hooks/__init__.py +43 -0
  158. batho/hooks/bootstrap.py +18 -0
  159. batho/hooks/constants.py +97 -0
  160. batho/hooks/installer.py +159 -0
  161. batho/hooks/loader.py +63 -0
  162. batho/hooks/models.py +78 -0
  163. batho/hooks/planner.py +128 -0
  164. batho/hooks/runner.py +147 -0
  165. batho/synthesizer.py +249 -0
  166. batho/time_machine.py +1667 -0
  167. batho/utils/__init__.py +54 -0
  168. batho/utils/cli_output.py +165 -0
  169. batho/utils/dependencies.py +618 -0
  170. batho/utils/encoding.py +106 -0
  171. batho/utils/file_io.py +194 -0
  172. batho/utils/file_lock.py +294 -0
  173. batho/utils/hash.py +214 -0
  174. batho/utils/ignore.py +379 -0
  175. batho/utils/logging.py +160 -0
  176. batho/utils/memory_monitor.py +304 -0
  177. batho/utils/patch_errors.py +279 -0
  178. batho/utils/path_sanitizer.py +237 -0
  179. batho-0.1.4.dist-info/METADATA +1378 -0
  180. batho-0.1.4.dist-info/RECORD +184 -0
  181. batho-0.1.4.dist-info/WHEEL +4 -0
  182. batho-0.1.4.dist-info/entry_points.txt +2 -0
  183. batho-0.1.4.dist-info/licenses/LICENSE +201 -0
  184. batho_cli.py +3922 -0
batho/__init__.py ADDED
@@ -0,0 +1,55 @@
1
+ """
2
+ Batho Core - Code analysis and indexing library.
3
+
4
+ This package provides the core functionality for analyzing code repositories,
5
+ building dependency graphs, and generating contextual information for LLMs.
6
+ """
7
+
8
+ __version__ = "0.1.3"
9
+
10
+ from batho.config import get_config_cached, reload_config
11
+ from batho.context.bsg_map import BSGMap
12
+
13
+ # Import and re-export public APIs from submodules
14
+ from batho.context.codegraph import CodeGraphIndexer, InMemoryGraph
15
+ from batho.context.incremental import get_changed_file_status_since
16
+ from batho.context.query import QueryService
17
+ from batho.time_machine import (
18
+ FileChange,
19
+ FileChangeSummary,
20
+ FileChangeTracker,
21
+ FileChangeType,
22
+ create_snapshot,
23
+ diff_snapshots,
24
+ incremental_patch,
25
+ list_snapshots,
26
+ load_snapshot,
27
+ )
28
+ from batho.utils.logging import get_logger
29
+
30
+ __all__ = [
31
+ # Core indexing
32
+ "CodeGraphIndexer",
33
+ "InMemoryGraph",
34
+ # Query service
35
+ "QueryService",
36
+ # BSG rendering
37
+ "BSGMap",
38
+ # Incremental
39
+ "get_changed_file_status_since",
40
+ # Time machine
41
+ "create_snapshot",
42
+ "diff_snapshots",
43
+ "FileChange",
44
+ "FileChangeSummary",
45
+ "FileChangeTracker",
46
+ "FileChangeType",
47
+ "incremental_patch",
48
+ "list_snapshots",
49
+ "load_snapshot",
50
+ # Config
51
+ "get_config_cached",
52
+ "reload_config",
53
+ # Logging
54
+ "get_logger",
55
+ ]
@@ -0,0 +1,42 @@
1
+ """Batho bridge — access .ctn artifacts via registry, REST, and MCP."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from batho.bridge.artifact_loader import (
6
+ ArtifactContent,
7
+ ArtifactLoader,
8
+ ArtifactNotFoundError,
9
+ ArtifactParseError,
10
+ ChecksumMismatchError,
11
+ )
12
+ from batho.bridge.http_api import BridgeAPIHandler, create_bridge_server
13
+ from batho.bridge.mcp_server import create_mcp_server, run_mcp_sse, run_mcp_stdio
14
+ from batho.bridge.models import (
15
+ ArtifactRecord,
16
+ BridgeErrorResponse,
17
+ BridgeResponse,
18
+ IndexEntry,
19
+ RegistryStats,
20
+ )
21
+ from batho.bridge.registry_client import ArtifactRegistryBridge
22
+
23
+ __version__ = "0.1.0"
24
+
25
+ __all__ = [
26
+ "ArtifactContent",
27
+ "ArtifactLoader",
28
+ "ArtifactNotFoundError",
29
+ "ArtifactParseError",
30
+ "ArtifactRecord",
31
+ "ArtifactRegistryBridge",
32
+ "BridgeAPIHandler",
33
+ "BridgeErrorResponse",
34
+ "BridgeResponse",
35
+ "ChecksumMismatchError",
36
+ "IndexEntry",
37
+ "RegistryStats",
38
+ "create_bridge_server",
39
+ "create_mcp_server",
40
+ "run_mcp_sse",
41
+ "run_mcp_stdio",
42
+ ]
@@ -0,0 +1,214 @@
1
+ """Artifact loader — resolves paths and loads JSON content from .ctn artifacts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ from batho.bridge.constants import DEFAULT_PATH_PATTERNS, INDEX_SCOPED_TYPES
12
+ from batho.bridge.models import ArtifactRecord
13
+ from batho.bridge.registry_client import ArtifactRegistryBridge
14
+ from batho.utils.hash import compute_file_hash
15
+ from batho.utils.logging import get_logger
16
+
17
+ LOGGER = get_logger(__name__, component="bridge")
18
+
19
+
20
+ class ArtifactNotFoundError(Exception):
21
+ """Raised when an artifact cannot be resolved on disk."""
22
+
23
+ def __init__(self, artifact_type: str, resolved_path: str) -> None:
24
+ super().__init__(f"Artifact not found: {artifact_type} at {resolved_path}")
25
+ self.artifact_type = artifact_type
26
+ self.resolved_path = resolved_path
27
+
28
+
29
+ class ChecksumMismatchError(Exception):
30
+ """Raised when the on-disk checksum does not match the registry."""
31
+
32
+ def __init__(self, artifact_type: str, expected: str, actual: str) -> None:
33
+ super().__init__(
34
+ f"Checksum mismatch for {artifact_type}: expected {expected}, got {actual}"
35
+ )
36
+ self.artifact_type = artifact_type
37
+ self.expected = expected
38
+ self.actual = actual
39
+
40
+
41
+ class ArtifactParseError(Exception):
42
+ """Raised when JSON parsing fails."""
43
+
44
+ def __init__(self, artifact_type: str, path: str, message: str) -> None:
45
+ super().__init__(f"Parse error in {artifact_type} ({path}): {message}")
46
+ self.artifact_type = artifact_type
47
+ self.path = path
48
+
49
+
50
+ @dataclass
51
+ class ArtifactContent:
52
+ """Loaded artifact with metadata."""
53
+
54
+ record: ArtifactRecord
55
+ data: dict[str, Any]
56
+ resolved_path: str
57
+ checksum_verified: bool
58
+
59
+
60
+ class ArtifactLoader:
61
+ """Resolves artifact paths and loads JSON content with fallbacks."""
62
+
63
+ def __init__(self, ctn_dir: Path) -> None:
64
+ self.ctn_dir = ctn_dir.resolve()
65
+ self._bridge = ArtifactRegistryBridge(self.ctn_dir)
66
+
67
+ def _resolve_index_id(self) -> str | None:
68
+ """Return the current index_id from index.json, if any."""
69
+ latest = self._bridge.get_latest_index()
70
+ return latest.index_id if latest else None
71
+
72
+ def _resolve_path(self, artifact_type: str, index_id: str | None = None) -> Path | None:
73
+ """Resolve the filesystem path for an artifact type.
74
+
75
+ Resolution order:
76
+ 1. Registry lookup by type (most recent active artifact).
77
+ 2. Default pattern using provided or current index_id.
78
+ 3. index.json ``outputs`` map lookup.
79
+ """
80
+ # 1. Registry lookup
81
+ candidates = self._bridge.get_artifacts_by_type(artifact_type, limit=1)
82
+ if candidates:
83
+ record = candidates[0]
84
+ phys = Path(record.physical_path)
85
+ if phys.exists():
86
+ return phys
87
+ logical = self.ctn_dir / record.logical_path
88
+ if logical.exists():
89
+ return logical
90
+
91
+ # 2. Default pattern
92
+ pattern = DEFAULT_PATH_PATTERNS.get(artifact_type)
93
+ if pattern:
94
+ if artifact_type in INDEX_SCOPED_TYPES:
95
+ idx = index_id or self._resolve_index_id()
96
+ if idx:
97
+ resolved = self.ctn_dir / pattern.format(index_id=idx)
98
+ if resolved.exists():
99
+ return resolved
100
+ else:
101
+ resolved = self.ctn_dir / pattern
102
+ if resolved.exists():
103
+ return resolved
104
+
105
+ # 3. index.json outputs map
106
+ latest = self._bridge.get_latest_index()
107
+ if latest and latest.outputs:
108
+ output_key = _artifact_type_to_output_key(artifact_type)
109
+ if output_key:
110
+ rel_path = latest.outputs.get(output_key)
111
+ if rel_path:
112
+ candidate = (self.ctn_dir.parent / rel_path).resolve()
113
+ if candidate.exists():
114
+ return candidate
115
+ # Try relative to ctn_dir itself
116
+ candidate2 = self.ctn_dir / rel_path
117
+ if candidate2.exists():
118
+ return candidate2
119
+
120
+ return None
121
+
122
+ def load_json(
123
+ self,
124
+ artifact_type: str,
125
+ *,
126
+ index_id: str | None = None,
127
+ verify_checksum: bool = True,
128
+ ) -> dict[str, Any]:
129
+ """Load and return the JSON content for an artifact type.
130
+
131
+ Raises:
132
+ ArtifactNotFoundError: if no file can be resolved.
133
+ ChecksumMismatchError: if checksum verification fails.
134
+ ArtifactParseError: if JSON parsing fails.
135
+ """
136
+ path = self._resolve_path(artifact_type, index_id=index_id)
137
+ if path is None or not path.exists():
138
+ raise ArtifactNotFoundError(artifact_type, str(path) if path else "<unresolved>")
139
+
140
+ # Checksum verification
141
+ record: ArtifactRecord | None = None
142
+ candidates = self._bridge.get_artifacts_by_type(artifact_type, limit=1)
143
+ if candidates:
144
+ record = candidates[0]
145
+
146
+ checksum_verified = False
147
+ if verify_checksum and record and record.checksum:
148
+ actual = compute_file_hash(path) or ""
149
+ if actual and actual != record.checksum:
150
+ raise ChecksumMismatchError(artifact_type, record.checksum, actual)
151
+ checksum_verified = actual == record.checksum
152
+
153
+ # Load JSON
154
+ try:
155
+ raw = path.read_text(encoding="utf-8")
156
+ data: dict[str, Any] = json.loads(raw)
157
+ except (OSError, json.JSONDecodeError) as exc:
158
+ raise ArtifactParseError(artifact_type, str(path), str(exc))
159
+
160
+ if not isinstance(data, dict):
161
+ raise ArtifactParseError(artifact_type, str(path), "top-level value is not an object")
162
+
163
+ return data
164
+
165
+ def load_artifact(self, record: ArtifactRecord, *, verify_checksum: bool = True) -> ArtifactContent:
166
+ """Load a specific artifact by its registry record."""
167
+ path = Path(record.physical_path)
168
+ if not path.exists():
169
+ path = self.ctn_dir / record.logical_path
170
+ if not path.exists():
171
+ raise ArtifactNotFoundError(record.artifact_type, str(record.physical_path))
172
+
173
+ checksum_verified = False
174
+ if verify_checksum and record.checksum:
175
+ actual = compute_file_hash(path) or ""
176
+ if actual and actual != record.checksum:
177
+ raise ChecksumMismatchError(record.artifact_type, record.checksum, actual)
178
+ checksum_verified = actual == record.checksum
179
+
180
+ try:
181
+ raw = path.read_text(encoding="utf-8")
182
+ data = json.loads(raw)
183
+ except (OSError, json.JSONDecodeError) as exc:
184
+ raise ArtifactParseError(record.artifact_type, str(path), str(exc))
185
+
186
+ if not isinstance(data, dict):
187
+ raise ArtifactParseError(record.artifact_type, str(path), "top-level value is not an object")
188
+
189
+ return ArtifactContent(
190
+ record=record,
191
+ data=data,
192
+ resolved_path=str(path),
193
+ checksum_verified=checksum_verified,
194
+ )
195
+
196
+
197
+ def _artifact_type_to_output_key(artifact_type: str) -> str | None:
198
+ """Map artifact types to keys used in index.json ``outputs``."""
199
+ mapping = {
200
+ "graph_json": "graph_json",
201
+ "bsg_json": "bsg_json",
202
+ "context_overview_json": "overview_json",
203
+ "context_files_json": "files_json",
204
+ }
205
+ return mapping.get(artifact_type)
206
+
207
+
208
+ __all__ = [
209
+ "ArtifactLoader",
210
+ "ArtifactContent",
211
+ "ArtifactNotFoundError",
212
+ "ChecksumMismatchError",
213
+ "ArtifactParseError",
214
+ ]
@@ -0,0 +1,79 @@
1
+ """Artifact type constants and path mappings for the Batho bridge."""
2
+
3
+ from __future__ import annotations
4
+
5
+ # Artifact types that the bridge can load as JSON
6
+ KNOWN_ARTIFACT_TYPES: set[str] = {
7
+ "interception_stats_json",
8
+ "graph_json",
9
+ "bsg_json",
10
+ "context_overview_json",
11
+ "context_files_json",
12
+ "snapshot_json",
13
+ "index_metadata",
14
+ "metrics_json",
15
+ "file_hashes_json",
16
+ "patches_index",
17
+ "patch_detail",
18
+ }
19
+
20
+ # Default logical path patterns relative to .ctn/ for each artifact type.
21
+ # The {index_id} placeholder is resolved from the current index.
22
+ DEFAULT_PATH_PATTERNS: dict[str, str] = {
23
+ "interception_stats_json": "local/metrics/interception_stats.json",
24
+ "graph_json": "{index_id}/graph.json",
25
+ "bsg_json": "{index_id}/bsg.json",
26
+ "context_overview_json": "{index_id}/context/json/overview.json",
27
+ "context_files_json": "{index_id}/context/json/files.json",
28
+ "snapshot_json": "snapshots/{name}.json",
29
+ "index_metadata": "index.json",
30
+ "metrics_json": "local/metrics/metrics.json",
31
+ "file_hashes_json": "local/state/file_hashes.json",
32
+ "patches_index": "patches/index.json",
33
+ "patch_detail": "patches/patch_{operation_id}.json",
34
+ }
35
+
36
+ # Artifact types that require an index_id for path resolution
37
+ INDEX_SCOPED_TYPES: set[str] = {
38
+ "graph_json",
39
+ "bsg_json",
40
+ "context_overview_json",
41
+ "context_files_json",
42
+ }
43
+
44
+ # Registry column names exposed by the bridge API
45
+ ARTIFACT_RECORD_FIELDS: tuple[str, ...] = (
46
+ "artifact_id",
47
+ "content_id",
48
+ "artifact_type",
49
+ "logical_path",
50
+ "physical_path",
51
+ "checksum",
52
+ "size_bytes",
53
+ "schema_version",
54
+ "producer",
55
+ "run_id",
56
+ "sync_status",
57
+ "cloud_content_id",
58
+ "last_sync_at",
59
+ "sync_error",
60
+ "retry_count",
61
+ "retention_class",
62
+ "metadata",
63
+ "created_at",
64
+ "updated_at",
65
+ )
66
+
67
+ DEFAULT_BRIDGE_HTTP_PORT = 8766
68
+ DEFAULT_MCP_SSE_PORT = 8767
69
+ DEFAULT_PAGE_LIMIT = 200
70
+
71
+ __all__ = [
72
+ "KNOWN_ARTIFACT_TYPES",
73
+ "DEFAULT_PATH_PATTERNS",
74
+ "INDEX_SCOPED_TYPES",
75
+ "ARTIFACT_RECORD_FIELDS",
76
+ "DEFAULT_BRIDGE_HTTP_PORT",
77
+ "DEFAULT_MCP_SSE_PORT",
78
+ "DEFAULT_PAGE_LIMIT",
79
+ ]