alma-memory 0.5.1__py3-none-any.whl → 0.7.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 (111) hide show
  1. alma/__init__.py +296 -226
  2. alma/compression/__init__.py +33 -0
  3. alma/compression/pipeline.py +980 -0
  4. alma/confidence/__init__.py +47 -47
  5. alma/confidence/engine.py +540 -540
  6. alma/confidence/types.py +351 -351
  7. alma/config/loader.py +157 -157
  8. alma/consolidation/__init__.py +23 -23
  9. alma/consolidation/engine.py +678 -678
  10. alma/consolidation/prompts.py +84 -84
  11. alma/core.py +1189 -430
  12. alma/domains/__init__.py +30 -30
  13. alma/domains/factory.py +359 -359
  14. alma/domains/schemas.py +448 -448
  15. alma/domains/types.py +272 -272
  16. alma/events/__init__.py +75 -75
  17. alma/events/emitter.py +285 -284
  18. alma/events/storage_mixin.py +246 -246
  19. alma/events/types.py +126 -126
  20. alma/events/webhook.py +425 -425
  21. alma/exceptions.py +49 -49
  22. alma/extraction/__init__.py +31 -31
  23. alma/extraction/auto_learner.py +265 -265
  24. alma/extraction/extractor.py +420 -420
  25. alma/graph/__init__.py +106 -106
  26. alma/graph/backends/__init__.py +32 -32
  27. alma/graph/backends/kuzu.py +624 -624
  28. alma/graph/backends/memgraph.py +432 -432
  29. alma/graph/backends/memory.py +236 -236
  30. alma/graph/backends/neo4j.py +417 -417
  31. alma/graph/base.py +159 -159
  32. alma/graph/extraction.py +198 -198
  33. alma/graph/store.py +860 -860
  34. alma/harness/__init__.py +35 -35
  35. alma/harness/base.py +386 -386
  36. alma/harness/domains.py +705 -705
  37. alma/initializer/__init__.py +37 -37
  38. alma/initializer/initializer.py +418 -418
  39. alma/initializer/types.py +250 -250
  40. alma/integration/__init__.py +62 -62
  41. alma/integration/claude_agents.py +444 -444
  42. alma/integration/helena.py +423 -423
  43. alma/integration/victor.py +471 -471
  44. alma/learning/__init__.py +101 -86
  45. alma/learning/decay.py +878 -0
  46. alma/learning/forgetting.py +1446 -1446
  47. alma/learning/heuristic_extractor.py +390 -390
  48. alma/learning/protocols.py +374 -374
  49. alma/learning/validation.py +346 -346
  50. alma/mcp/__init__.py +123 -45
  51. alma/mcp/__main__.py +156 -156
  52. alma/mcp/resources.py +122 -122
  53. alma/mcp/server.py +955 -591
  54. alma/mcp/tools.py +3254 -509
  55. alma/observability/__init__.py +91 -84
  56. alma/observability/config.py +302 -302
  57. alma/observability/guidelines.py +170 -0
  58. alma/observability/logging.py +424 -424
  59. alma/observability/metrics.py +583 -583
  60. alma/observability/tracing.py +440 -440
  61. alma/progress/__init__.py +21 -21
  62. alma/progress/tracker.py +607 -607
  63. alma/progress/types.py +250 -250
  64. alma/retrieval/__init__.py +134 -53
  65. alma/retrieval/budget.py +525 -0
  66. alma/retrieval/cache.py +1304 -1061
  67. alma/retrieval/embeddings.py +202 -202
  68. alma/retrieval/engine.py +850 -427
  69. alma/retrieval/modes.py +365 -0
  70. alma/retrieval/progressive.py +560 -0
  71. alma/retrieval/scoring.py +344 -344
  72. alma/retrieval/trust_scoring.py +637 -0
  73. alma/retrieval/verification.py +797 -0
  74. alma/session/__init__.py +19 -19
  75. alma/session/manager.py +442 -399
  76. alma/session/types.py +288 -288
  77. alma/storage/__init__.py +101 -90
  78. alma/storage/archive.py +233 -0
  79. alma/storage/azure_cosmos.py +1259 -1259
  80. alma/storage/base.py +1083 -583
  81. alma/storage/chroma.py +1443 -1443
  82. alma/storage/constants.py +103 -103
  83. alma/storage/file_based.py +614 -614
  84. alma/storage/migrations/__init__.py +21 -21
  85. alma/storage/migrations/base.py +321 -321
  86. alma/storage/migrations/runner.py +323 -323
  87. alma/storage/migrations/version_stores.py +337 -337
  88. alma/storage/migrations/versions/__init__.py +11 -11
  89. alma/storage/migrations/versions/v1_0_0.py +373 -373
  90. alma/storage/migrations/versions/v1_1_0_workflow_context.py +551 -0
  91. alma/storage/pinecone.py +1080 -1080
  92. alma/storage/postgresql.py +1948 -1559
  93. alma/storage/qdrant.py +1306 -1306
  94. alma/storage/sqlite_local.py +3041 -1457
  95. alma/testing/__init__.py +46 -46
  96. alma/testing/factories.py +301 -301
  97. alma/testing/mocks.py +389 -389
  98. alma/types.py +292 -264
  99. alma/utils/__init__.py +19 -0
  100. alma/utils/tokenizer.py +521 -0
  101. alma/workflow/__init__.py +83 -0
  102. alma/workflow/artifacts.py +170 -0
  103. alma/workflow/checkpoint.py +311 -0
  104. alma/workflow/context.py +228 -0
  105. alma/workflow/outcomes.py +189 -0
  106. alma/workflow/reducers.py +393 -0
  107. {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/METADATA +210 -72
  108. alma_memory-0.7.0.dist-info/RECORD +112 -0
  109. alma_memory-0.5.1.dist-info/RECORD +0 -93
  110. {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/WHEEL +0 -0
  111. {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/top_level.txt +0 -0
@@ -1,21 +1,21 @@
1
- """
2
- ALMA Schema Migration Framework.
3
-
4
- Provides version tracking and migration capabilities for storage backends.
5
- """
6
-
7
- from alma.storage.migrations.base import (
8
- Migration,
9
- MigrationError,
10
- MigrationRegistry,
11
- SchemaVersion,
12
- )
13
- from alma.storage.migrations.runner import MigrationRunner
14
-
15
- __all__ = [
16
- "Migration",
17
- "MigrationError",
18
- "MigrationRegistry",
19
- "MigrationRunner",
20
- "SchemaVersion",
21
- ]
1
+ """
2
+ ALMA Schema Migration Framework.
3
+
4
+ Provides version tracking and migration capabilities for storage backends.
5
+ """
6
+
7
+ from alma.storage.migrations.base import (
8
+ Migration,
9
+ MigrationError,
10
+ MigrationRegistry,
11
+ SchemaVersion,
12
+ )
13
+ from alma.storage.migrations.runner import MigrationRunner
14
+
15
+ __all__ = [
16
+ "Migration",
17
+ "MigrationError",
18
+ "MigrationRegistry",
19
+ "MigrationRunner",
20
+ "SchemaVersion",
21
+ ]
@@ -1,321 +1,321 @@
1
- """
2
- ALMA Migration Framework - Base Classes.
3
-
4
- Provides abstract migration classes and version tracking utilities.
5
- """
6
-
7
- import logging
8
- from abc import ABC, abstractmethod
9
- from dataclasses import dataclass, field
10
- from datetime import datetime, timezone
11
- from typing import Any, Callable, Dict, List, Optional, Type
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
-
16
- class MigrationError(Exception):
17
- """Exception raised when a migration fails."""
18
-
19
- def __init__(
20
- self,
21
- message: str,
22
- version: Optional[str] = None,
23
- cause: Optional[Exception] = None,
24
- ):
25
- self.version = version
26
- self.cause = cause
27
- super().__init__(message)
28
-
29
-
30
- @dataclass
31
- class SchemaVersion:
32
- """
33
- Represents a schema version record.
34
-
35
- Attributes:
36
- version: Semantic version string (e.g., "1.0.0")
37
- applied_at: When the migration was applied
38
- description: Human-readable description of changes
39
- checksum: Optional hash for integrity verification
40
- """
41
-
42
- version: str
43
- applied_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
44
- description: str = ""
45
- checksum: Optional[str] = None
46
-
47
- def __lt__(self, other: "SchemaVersion") -> bool:
48
- """Compare versions for sorting."""
49
- return self._parse_version(self.version) < self._parse_version(other.version)
50
-
51
- @staticmethod
52
- def _parse_version(version: str) -> tuple:
53
- """Parse version string into comparable tuple."""
54
- parts = version.split(".")
55
- result = []
56
- for part in parts:
57
- try:
58
- result.append(int(part))
59
- except ValueError:
60
- result.append(part)
61
- return tuple(result)
62
-
63
-
64
- class Migration(ABC):
65
- """
66
- Abstract base class for schema migrations.
67
-
68
- Subclasses must implement upgrade() and optionally downgrade().
69
-
70
- Example:
71
- class AddTagsColumn(Migration):
72
- version = "1.1.0"
73
- description = "Add tags column to heuristics table"
74
-
75
- def upgrade(self, connection):
76
- connection.execute(
77
- "ALTER TABLE heuristics ADD COLUMN tags TEXT"
78
- )
79
-
80
- def downgrade(self, connection):
81
- connection.execute(
82
- "ALTER TABLE heuristics DROP COLUMN tags"
83
- )
84
- """
85
-
86
- # These must be set by subclasses
87
- version: str = ""
88
- description: str = ""
89
- # Optional: previous version this migration depends on
90
- depends_on: Optional[str] = None
91
-
92
- @abstractmethod
93
- def upgrade(self, connection: Any) -> None:
94
- """
95
- Apply the migration.
96
-
97
- Args:
98
- connection: Database connection or storage instance
99
- """
100
- pass
101
-
102
- def downgrade(self, connection: Any) -> None:
103
- """
104
- Revert the migration (optional).
105
-
106
- Args:
107
- connection: Database connection or storage instance
108
-
109
- Raises:
110
- NotImplementedError: If downgrade is not supported
111
- """
112
- raise NotImplementedError(
113
- f"Downgrade not implemented for migration {self.version}"
114
- )
115
-
116
- def pre_check(self, connection: Any) -> bool:
117
- """
118
- Optional pre-migration check.
119
-
120
- Override to verify prerequisites before migration.
121
-
122
- Args:
123
- connection: Database connection
124
-
125
- Returns:
126
- True if migration can proceed, False otherwise
127
- """
128
- return True
129
-
130
- def post_check(self, connection: Any) -> bool:
131
- """
132
- Optional post-migration verification.
133
-
134
- Override to verify migration was successful.
135
-
136
- Args:
137
- connection: Database connection
138
-
139
- Returns:
140
- True if migration was successful
141
- """
142
- return True
143
-
144
-
145
- class MigrationRegistry:
146
- """
147
- Registry for available migrations.
148
-
149
- Manages migration discovery, ordering, and execution planning.
150
- """
151
-
152
- def __init__(self) -> None:
153
- self._migrations: Dict[str, Type[Migration]] = {}
154
- self._backend_migrations: Dict[str, Dict[str, Type[Migration]]] = {}
155
-
156
- def register(
157
- self, migration_class: Type[Migration], backend: Optional[str] = None
158
- ) -> Type[Migration]:
159
- """
160
- Register a migration class.
161
-
162
- Args:
163
- migration_class: The migration class to register
164
- backend: Optional backend name (e.g., "sqlite", "postgresql")
165
-
166
- Returns:
167
- The migration class (for use as decorator)
168
- """
169
- version = migration_class.version
170
- if not version:
171
- raise ValueError(
172
- f"Migration {migration_class.__name__} must have a version"
173
- )
174
-
175
- if backend:
176
- if backend not in self._backend_migrations:
177
- self._backend_migrations[backend] = {}
178
- self._backend_migrations[backend][version] = migration_class
179
- logger.debug(f"Registered migration {version} for backend {backend}")
180
- else:
181
- self._migrations[version] = migration_class
182
- logger.debug(f"Registered global migration {version}")
183
-
184
- return migration_class
185
-
186
- def get_migration(
187
- self, version: str, backend: Optional[str] = None
188
- ) -> Optional[Type[Migration]]:
189
- """
190
- Get a migration class by version.
191
-
192
- Args:
193
- version: Version string to look up
194
- backend: Optional backend name
195
-
196
- Returns:
197
- Migration class or None if not found
198
- """
199
- if backend and backend in self._backend_migrations:
200
- migration = self._backend_migrations[backend].get(version)
201
- if migration:
202
- return migration
203
- return self._migrations.get(version)
204
-
205
- def get_all_migrations(
206
- self, backend: Optional[str] = None
207
- ) -> List[Type[Migration]]:
208
- """
209
- Get all migrations in version order.
210
-
211
- Args:
212
- backend: Optional backend name to filter migrations
213
-
214
- Returns:
215
- List of migration classes sorted by version
216
- """
217
- migrations = dict(self._migrations)
218
- if backend and backend in self._backend_migrations:
219
- migrations.update(self._backend_migrations[backend])
220
-
221
- return [
222
- cls
223
- for _, cls in sorted(
224
- migrations.items(),
225
- key=lambda x: SchemaVersion._parse_version(x[0]),
226
- )
227
- ]
228
-
229
- def get_pending_migrations(
230
- self,
231
- current_version: Optional[str],
232
- backend: Optional[str] = None,
233
- ) -> List[Type[Migration]]:
234
- """
235
- Get migrations that need to be applied.
236
-
237
- Args:
238
- current_version: Current schema version (None if fresh install)
239
- backend: Optional backend name
240
-
241
- Returns:
242
- List of migration classes that need to be applied
243
- """
244
- all_migrations = self.get_all_migrations(backend)
245
-
246
- if current_version is None:
247
- return all_migrations
248
-
249
- current = SchemaVersion._parse_version(current_version)
250
- return [
251
- m
252
- for m in all_migrations
253
- if SchemaVersion._parse_version(m.version) > current
254
- ]
255
-
256
- def get_rollback_migrations(
257
- self,
258
- current_version: str,
259
- target_version: str,
260
- backend: Optional[str] = None,
261
- ) -> List[Type[Migration]]:
262
- """
263
- Get migrations that need to be rolled back.
264
-
265
- Args:
266
- current_version: Current schema version
267
- target_version: Target version to roll back to
268
- backend: Optional backend name
269
-
270
- Returns:
271
- List of migration classes to roll back (in reverse order)
272
- """
273
- all_migrations = self.get_all_migrations(backend)
274
-
275
- current = SchemaVersion._parse_version(current_version)
276
- target = SchemaVersion._parse_version(target_version)
277
-
278
- rollback = [
279
- m
280
- for m in all_migrations
281
- if target < SchemaVersion._parse_version(m.version) <= current
282
- ]
283
-
284
- # Return in reverse order for rollback
285
- return list(reversed(rollback))
286
-
287
-
288
- # Global registry instance
289
- _global_registry = MigrationRegistry()
290
-
291
-
292
- def register_migration(
293
- backend: Optional[str] = None,
294
- ) -> Callable[[Type[Migration]], Type[Migration]]:
295
- """
296
- Decorator to register a migration class.
297
-
298
- Args:
299
- backend: Optional backend name
300
-
301
- Example:
302
- @register_migration()
303
- class MyMigration(Migration):
304
- version = "1.0.0"
305
- ...
306
-
307
- @register_migration(backend="postgresql")
308
- class PostgresSpecificMigration(Migration):
309
- version = "1.0.1"
310
- ...
311
- """
312
-
313
- def decorator(cls: Type[Migration]) -> Type[Migration]:
314
- return _global_registry.register(cls, backend)
315
-
316
- return decorator
317
-
318
-
319
- def get_registry() -> MigrationRegistry:
320
- """Get the global migration registry."""
321
- return _global_registry
1
+ """
2
+ ALMA Migration Framework - Base Classes.
3
+
4
+ Provides abstract migration classes and version tracking utilities.
5
+ """
6
+
7
+ import logging
8
+ from abc import ABC, abstractmethod
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime, timezone
11
+ from typing import Any, Callable, Dict, List, Optional, Type
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class MigrationError(Exception):
17
+ """Exception raised when a migration fails."""
18
+
19
+ def __init__(
20
+ self,
21
+ message: str,
22
+ version: Optional[str] = None,
23
+ cause: Optional[Exception] = None,
24
+ ):
25
+ self.version = version
26
+ self.cause = cause
27
+ super().__init__(message)
28
+
29
+
30
+ @dataclass
31
+ class SchemaVersion:
32
+ """
33
+ Represents a schema version record.
34
+
35
+ Attributes:
36
+ version: Semantic version string (e.g., "1.0.0")
37
+ applied_at: When the migration was applied
38
+ description: Human-readable description of changes
39
+ checksum: Optional hash for integrity verification
40
+ """
41
+
42
+ version: str
43
+ applied_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
44
+ description: str = ""
45
+ checksum: Optional[str] = None
46
+
47
+ def __lt__(self, other: "SchemaVersion") -> bool:
48
+ """Compare versions for sorting."""
49
+ return self._parse_version(self.version) < self._parse_version(other.version)
50
+
51
+ @staticmethod
52
+ def _parse_version(version: str) -> tuple:
53
+ """Parse version string into comparable tuple."""
54
+ parts = version.split(".")
55
+ result = []
56
+ for part in parts:
57
+ try:
58
+ result.append(int(part))
59
+ except ValueError:
60
+ result.append(part)
61
+ return tuple(result)
62
+
63
+
64
+ class Migration(ABC):
65
+ """
66
+ Abstract base class for schema migrations.
67
+
68
+ Subclasses must implement upgrade() and optionally downgrade().
69
+
70
+ Example:
71
+ class AddTagsColumn(Migration):
72
+ version = "1.1.0"
73
+ description = "Add tags column to heuristics table"
74
+
75
+ def upgrade(self, connection):
76
+ connection.execute(
77
+ "ALTER TABLE heuristics ADD COLUMN tags TEXT"
78
+ )
79
+
80
+ def downgrade(self, connection):
81
+ connection.execute(
82
+ "ALTER TABLE heuristics DROP COLUMN tags"
83
+ )
84
+ """
85
+
86
+ # These must be set by subclasses
87
+ version: str = ""
88
+ description: str = ""
89
+ # Optional: previous version this migration depends on
90
+ depends_on: Optional[str] = None
91
+
92
+ @abstractmethod
93
+ def upgrade(self, connection: Any) -> None:
94
+ """
95
+ Apply the migration.
96
+
97
+ Args:
98
+ connection: Database connection or storage instance
99
+ """
100
+ pass
101
+
102
+ def downgrade(self, connection: Any) -> None:
103
+ """
104
+ Revert the migration (optional).
105
+
106
+ Args:
107
+ connection: Database connection or storage instance
108
+
109
+ Raises:
110
+ NotImplementedError: If downgrade is not supported
111
+ """
112
+ raise NotImplementedError(
113
+ f"Downgrade not implemented for migration {self.version}"
114
+ )
115
+
116
+ def pre_check(self, connection: Any) -> bool:
117
+ """
118
+ Optional pre-migration check.
119
+
120
+ Override to verify prerequisites before migration.
121
+
122
+ Args:
123
+ connection: Database connection
124
+
125
+ Returns:
126
+ True if migration can proceed, False otherwise
127
+ """
128
+ return True
129
+
130
+ def post_check(self, connection: Any) -> bool:
131
+ """
132
+ Optional post-migration verification.
133
+
134
+ Override to verify migration was successful.
135
+
136
+ Args:
137
+ connection: Database connection
138
+
139
+ Returns:
140
+ True if migration was successful
141
+ """
142
+ return True
143
+
144
+
145
+ class MigrationRegistry:
146
+ """
147
+ Registry for available migrations.
148
+
149
+ Manages migration discovery, ordering, and execution planning.
150
+ """
151
+
152
+ def __init__(self) -> None:
153
+ self._migrations: Dict[str, Type[Migration]] = {}
154
+ self._backend_migrations: Dict[str, Dict[str, Type[Migration]]] = {}
155
+
156
+ def register(
157
+ self, migration_class: Type[Migration], backend: Optional[str] = None
158
+ ) -> Type[Migration]:
159
+ """
160
+ Register a migration class.
161
+
162
+ Args:
163
+ migration_class: The migration class to register
164
+ backend: Optional backend name (e.g., "sqlite", "postgresql")
165
+
166
+ Returns:
167
+ The migration class (for use as decorator)
168
+ """
169
+ version = migration_class.version
170
+ if not version:
171
+ raise ValueError(
172
+ f"Migration {migration_class.__name__} must have a version"
173
+ )
174
+
175
+ if backend:
176
+ if backend not in self._backend_migrations:
177
+ self._backend_migrations[backend] = {}
178
+ self._backend_migrations[backend][version] = migration_class
179
+ logger.debug(f"Registered migration {version} for backend {backend}")
180
+ else:
181
+ self._migrations[version] = migration_class
182
+ logger.debug(f"Registered global migration {version}")
183
+
184
+ return migration_class
185
+
186
+ def get_migration(
187
+ self, version: str, backend: Optional[str] = None
188
+ ) -> Optional[Type[Migration]]:
189
+ """
190
+ Get a migration class by version.
191
+
192
+ Args:
193
+ version: Version string to look up
194
+ backend: Optional backend name
195
+
196
+ Returns:
197
+ Migration class or None if not found
198
+ """
199
+ if backend and backend in self._backend_migrations:
200
+ migration = self._backend_migrations[backend].get(version)
201
+ if migration:
202
+ return migration
203
+ return self._migrations.get(version)
204
+
205
+ def get_all_migrations(
206
+ self, backend: Optional[str] = None
207
+ ) -> List[Type[Migration]]:
208
+ """
209
+ Get all migrations in version order.
210
+
211
+ Args:
212
+ backend: Optional backend name to filter migrations
213
+
214
+ Returns:
215
+ List of migration classes sorted by version
216
+ """
217
+ migrations = dict(self._migrations)
218
+ if backend and backend in self._backend_migrations:
219
+ migrations.update(self._backend_migrations[backend])
220
+
221
+ return [
222
+ cls
223
+ for _, cls in sorted(
224
+ migrations.items(),
225
+ key=lambda x: SchemaVersion._parse_version(x[0]),
226
+ )
227
+ ]
228
+
229
+ def get_pending_migrations(
230
+ self,
231
+ current_version: Optional[str],
232
+ backend: Optional[str] = None,
233
+ ) -> List[Type[Migration]]:
234
+ """
235
+ Get migrations that need to be applied.
236
+
237
+ Args:
238
+ current_version: Current schema version (None if fresh install)
239
+ backend: Optional backend name
240
+
241
+ Returns:
242
+ List of migration classes that need to be applied
243
+ """
244
+ all_migrations = self.get_all_migrations(backend)
245
+
246
+ if current_version is None:
247
+ return all_migrations
248
+
249
+ current = SchemaVersion._parse_version(current_version)
250
+ return [
251
+ m
252
+ for m in all_migrations
253
+ if SchemaVersion._parse_version(m.version) > current
254
+ ]
255
+
256
+ def get_rollback_migrations(
257
+ self,
258
+ current_version: str,
259
+ target_version: str,
260
+ backend: Optional[str] = None,
261
+ ) -> List[Type[Migration]]:
262
+ """
263
+ Get migrations that need to be rolled back.
264
+
265
+ Args:
266
+ current_version: Current schema version
267
+ target_version: Target version to roll back to
268
+ backend: Optional backend name
269
+
270
+ Returns:
271
+ List of migration classes to roll back (in reverse order)
272
+ """
273
+ all_migrations = self.get_all_migrations(backend)
274
+
275
+ current = SchemaVersion._parse_version(current_version)
276
+ target = SchemaVersion._parse_version(target_version)
277
+
278
+ rollback = [
279
+ m
280
+ for m in all_migrations
281
+ if target < SchemaVersion._parse_version(m.version) <= current
282
+ ]
283
+
284
+ # Return in reverse order for rollback
285
+ return list(reversed(rollback))
286
+
287
+
288
+ # Global registry instance
289
+ _global_registry = MigrationRegistry()
290
+
291
+
292
+ def register_migration(
293
+ backend: Optional[str] = None,
294
+ ) -> Callable[[Type[Migration]], Type[Migration]]:
295
+ """
296
+ Decorator to register a migration class.
297
+
298
+ Args:
299
+ backend: Optional backend name
300
+
301
+ Example:
302
+ @register_migration()
303
+ class MyMigration(Migration):
304
+ version = "1.0.0"
305
+ ...
306
+
307
+ @register_migration(backend="postgresql")
308
+ class PostgresSpecificMigration(Migration):
309
+ version = "1.0.1"
310
+ ...
311
+ """
312
+
313
+ def decorator(cls: Type[Migration]) -> Type[Migration]:
314
+ return _global_registry.register(cls, backend)
315
+
316
+ return decorator
317
+
318
+
319
+ def get_registry() -> MigrationRegistry:
320
+ """Get the global migration registry."""
321
+ return _global_registry