mainsequence 4.1.16__tar.gz → 4.1.18__tar.gz

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 (129) hide show
  1. {mainsequence-4.1.16/mainsequence.egg-info → mainsequence-4.1.18}/PKG-INFO +2 -1
  2. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +19 -35
  3. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +63 -92
  4. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/api.py +34 -34
  5. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/cli.py +9 -3
  6. mainsequence-4.1.18/mainsequence/cli/migrations.py +370 -0
  7. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/__init__.py +1 -1
  8. mainsequence-4.1.18/mainsequence/client/metatables/__init__.py +36 -0
  9. mainsequence-4.1.16/mainsequence/client/models_metatables.py → mainsequence-4.1.18/mainsequence/client/metatables/core.py +7 -278
  10. mainsequence-4.1.18/mainsequence/client/metatables/migrations.py +152 -0
  11. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_foundry.py +9 -6
  12. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_helpers.py +1 -1
  13. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/__init__.py +43 -11
  14. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/compiled_sql/v1.py +1 -1
  15. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/build_operations.py +1 -1
  16. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/data_nodes.py +1 -1
  17. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/persist_managers.py +3 -1
  18. mainsequence-4.1.18/mainsequence/meta_tables/migrations.py +594 -0
  19. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/sqlalchemy_contracts.py +33 -194
  20. {mainsequence-4.1.16 → mainsequence-4.1.18/mainsequence.egg-info}/PKG-INFO +2 -1
  21. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/SOURCES.txt +5 -1
  22. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/requires.txt +1 -0
  23. {mainsequence-4.1.16 → mainsequence-4.1.18}/pyproject.toml +2 -1
  24. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_build_operations_hashing.py +1 -1
  25. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_cli.py +38 -22
  26. mainsequence-4.1.18/tests/test_cli_migrations.py +338 -0
  27. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_node_storage_dimension_queries.py +1 -1
  28. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_node_update_flow.py +1 -1
  29. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_dependency_extras.py +1 -1
  30. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_duckdb_interface_dimensions.py +1 -1
  31. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_filter_normalization.py +12 -12
  32. mainsequence-4.1.18/tests/test_meta_table_migrations.py +457 -0
  33. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_meta_tables_client_models.py +40 -87
  34. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_meta_tables_sqlalchemy_contracts.py +80 -113
  35. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_pod_project_resolution.py +1 -1
  36. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_run_configuration.py +5 -5
  37. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_source_table_configuration.py +1 -1
  38. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_sqlite_interface_dimensions.py +1 -1
  39. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_runner_uid_runtime.py +1 -1
  40. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_statistics.py +1 -1
  41. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_uid_guards.py +1 -1
  42. mainsequence-4.1.16/mainsequence/meta_tables/migrations.py +0 -745
  43. mainsequence-4.1.16/tests/test_meta_table_migrations.py +0 -443
  44. {mainsequence-4.1.16 → mainsequence-4.1.18}/LICENSE +0 -0
  45. {mainsequence-4.1.16 → mainsequence-4.1.18}/README.md +0 -0
  46. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/AGENTS.md +0 -0
  47. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
  48. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  49. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
  50. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  51. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
  52. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  53. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  54. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  55. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  56. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  57. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  58. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  59. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  60. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  61. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  62. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  63. {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  64. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/__init__.py +0 -0
  65. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/__main__.py +0 -0
  66. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/bootstrap.py +0 -0
  67. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/__init__.py +0 -0
  68. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/browser_auth.py +0 -0
  69. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/config.py +0 -0
  70. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/docker_utils.py +0 -0
  71. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/doctor.py +0 -0
  72. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/local_ops.py +0 -0
  73. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/model_filters.py +0 -0
  74. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/project_status.py +0 -0
  75. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/pydantic_cli.py +0 -0
  76. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/sdk_utils.py +0 -0
  77. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/ssh_utils.py +0 -0
  78. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/ui.py +0 -0
  79. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/agent_runtime_models.py +0 -0
  80. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/base.py +0 -0
  81. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/client.py +0 -0
  82. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/__init__.py +0 -0
  83. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/app_component.py +0 -0
  84. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/connections.py +0 -0
  85. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/data_models.py +0 -0
  86. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/workspace.py +0 -0
  87. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  88. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/compute_validation.py +0 -0
  89. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  90. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  91. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  92. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  93. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/dtype_codec.py +0 -0
  94. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/exceptions.py +0 -0
  95. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/fastapi/__init__.py +0 -0
  96. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/fastapi/auth.py +0 -0
  97. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_user.py +0 -0
  98. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/utils.py +0 -0
  99. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/defaults.py +0 -0
  100. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/instrumentation/__init__.py +0 -0
  101. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/instrumentation/utils.py +0 -0
  102. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/logconf.py +0 -0
  103. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/__main__.py +0 -0
  104. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  105. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  106. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  107. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  108. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  109. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  110. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/future_registry.py +0 -0
  111. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/hashing.py +0 -0
  112. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  113. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/runtime_flags.py +0 -0
  114. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/dependency_links.txt +0 -0
  115. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/entry_points.txt +0 -0
  116. {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/top_level.txt +0 -0
  117. {mainsequence-4.1.16 → mainsequence-4.1.18}/setup.cfg +0 -0
  118. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_auth_precedence.py +0 -0
  119. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_cli_browser_auth.py +0 -0
  120. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_client.py +0 -0
  121. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_app_component_models.py +0 -0
  122. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_data_models.py +0 -0
  123. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_models.py +0 -0
  124. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  125. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_logconf.py +0 -0
  126. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_models_user_request_bound_auth.py +0 -0
  127. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_project_batch_jobs_from_file.py +0 -0
  128. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_secret_client_model.py +0 -0
  129. {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.1.16
3
+ Version: 4.1.18
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -53,6 +53,7 @@ Classifier: Operating System :: OS Independent
53
53
  Requires-Python: >=3.11
54
54
  Description-Content-Type: text/markdown
55
55
  License-File: LICENSE
56
+ Requires-Dist: alembic>=1.18.4
56
57
  Requires-Dist: cachetools
57
58
  Requires-Dist: click>=8.3.0
58
59
  Requires-Dist: concurrent-log-handler
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mainsequence-data-nodes
3
- description: Use this skill when the task is about producing, changing, validating, or reviewing Main Sequence DataNode update processes. This skill owns DataNode update configuration, dependencies, update logic, hashing, namespaces, and validation against a PlatformTimeIndexMetaData or MigrationManagedTimeIndexMetaData storage contract. It does not own generic MetaTable governance, API route contracts, scheduling, sharing policy, or storage registration internals.
3
+ description: Use this skill when the task is about producing, changing, validating, or reviewing Main Sequence DataNode update processes. This skill owns DataNode update configuration, dependencies, update logic, hashing, namespaces, and validation against a PlatformTimeIndexMetaData storage contract. It does not own generic MetaTable governance, Alembic migration execution, API route contracts, scheduling, sharing policy, or storage registration internals.
4
4
  ---
5
5
 
6
6
  # Main Sequence Data Nodes
@@ -10,14 +10,12 @@ description: Use this skill when the task is about producing, changing, validati
10
10
  Use this skill when the task changes a DataNode producer.
11
11
 
12
12
  A DataNode is an update process. It is not the canonical storage model. Storage
13
- is defined by a `PlatformTimeIndexMetaData` SQLAlchemy model, or by
14
- `MigrationManagedTimeIndexMetaData` when the storage table must support
15
- in-place contract migrations.
13
+ is defined by a `PlatformTimeIndexMetaData` SQLAlchemy model. Physical schema
14
+ evolution is handled with Alembic, not a DataNode storage subclass.
16
15
 
17
16
  Canonical workflow:
18
17
 
19
- 1. Define a `PlatformTimeIndexMetaData` storage class, or
20
- `MigrationManagedTimeIndexMetaData` for migration-managed storage.
18
+ 1. Define a `PlatformTimeIndexMetaData` storage class.
21
19
  2. Construct the DataNode with `config=...` and `storage_table=StorageClass`.
22
20
  3. Let the SDK register the output storage class automatically when needed.
23
21
  4. Return a DataFrame from `update()` that matches the storage class contract.
@@ -34,8 +32,7 @@ Canonical workflow:
34
32
  - `update()`
35
33
  - `prepare_update_statistics()`
36
34
  - design single-index or multidimensional time-first DataFrame outputs
37
- - validate output shape against a `PlatformTimeIndexMetaData` or
38
- `MigrationManagedTimeIndexMetaData` storage contract
35
+ - validate output shape against a `PlatformTimeIndexMetaData` storage contract
39
36
  - define explicit `hash_namespace(...)` validation strategy
40
37
  - write or review DataNode smoke tests
41
38
  - decide whether a consumer should use `APIDataNode`
@@ -80,8 +77,7 @@ If the task depends on one of those areas, route it explicitly instead of guessi
80
77
  Before changing code, collect or infer:
81
78
 
82
79
  - dataset meaning
83
- - `PlatformTimeIndexMetaData` or `MigrationManagedTimeIndexMetaData` output
84
- storage class, or the class to create
80
+ - `PlatformTimeIndexMetaData` output storage class, or the class to create
85
81
  - expected time index and identity index shape
86
82
  - expected columns and dtypes from the storage class
87
83
  - upstream dependencies
@@ -195,8 +191,7 @@ during bootstrap when code needs the returned metadata object:
195
191
  PricesTable.register()
196
192
  ```
197
193
 
198
- `PlatformTimeIndexMetaData.register()` and
199
- `MigrationManagedTimeIndexMetaData.register()` are the storage lifecycle paths.
194
+ `PlatformTimeIndexMetaData.register()` is the storage lifecycle path.
200
195
  Treat them as idempotent get-or-create operations: the platform returns the
201
196
  registered metadata and UID, and the SDK records that metadata on the class. Do
202
197
  not manually attach an existing UID, reconstruct a generic `MetaTable`, or use
@@ -215,16 +210,13 @@ The constructor `storage_table` is the output storage contract. Keep it out of
215
210
  construct the node; `DataNode` and `PersistManager` call the SDK registration
216
211
  lifecycle automatically when the class is not yet bound.
217
212
 
218
- `MigrationManagedTimeIndexMetaData` subclasses `PlatformTimeIndexMetaData`, so
219
- it is valid anywhere the DataNode API expects `type[PlatformTimeIndexMetaData]`.
220
-
221
213
  If the DataNode needs to select another DataNode's storage table as a
222
214
  dependency, put that dependency storage reference in the config as
223
215
  `type[PlatformTimeIndexMetaData]`. Do not add an extra constructor argument for
224
216
  dependency storage tables. Config values of this type are hashed by the bound
225
- `TimeIndexMetaData.uid` from `StorageClass.__time_index_metadata__`; this also
226
- applies to `MigrationManagedTimeIndexMetaData`. If the class is not yet bound,
227
- the config serializer calls `StorageClass.register()` before reading the UID.
217
+ `TimeIndexMetaData.uid` from `StorageClass.__time_index_metadata__`. If the
218
+ class is not yet bound, the config serializer calls `StorageClass.register()`
219
+ before reading the UID.
228
220
 
229
221
  Do not accept `test_node`. It has been removed. Use explicit
230
222
  `hash_namespace(...)` or `hash_namespace="..."`.
@@ -379,15 +371,10 @@ The validator error to prevent is:
379
371
  Time index must be datetime64[ns, UTC]
380
372
  ```
381
373
 
382
- Use `MigrationManagedTimeIndexMetaData` from the first version when a DataNode
383
- storage table must support in-place contract migrations through a
384
- `MigrationMetaTable` registry. It subclasses `PlatformTimeIndexMetaData`, keeps
385
- the TimeIndexMetaData registration endpoint and time-index validation, and uses
386
- stable identifier-addressed storage identity so contract hashes can rotate.
387
-
388
- Do not switch an already published shape-addressed `PlatformTimeIndexMetaData`
389
- table to migration-managed identity without an adoption plan for the old
390
- MetaTable UID/storage hash.
374
+ Use Alembic from the first version when a DataNode storage table must support
375
+ physical schema evolution. Keep the `PlatformTimeIndexMetaData` catalog model as
376
+ the SDK storage contract, apply Alembic-rendered SQL through the migration
377
+ workflow, then register or refresh the MetaTable catalog binding separately.
391
378
 
392
379
  ### 7. Dependencies Must Be Deterministic
393
380
 
@@ -400,10 +387,9 @@ Do not construct dependency graphs dynamically inside `update()`.
400
387
 
401
388
  ### 8. Foreign Keys Belong To The Storage Contract
402
389
 
403
- For new code, model foreign keys on the `PlatformTimeIndexMetaData` or
404
- `MigrationManagedTimeIndexMetaData` storage class, or route the
405
- storage-contract work to the MetaTable skill. When a DataNode storage table
406
- needs a platform-managed FK, use
390
+ For new code, model foreign keys on the `PlatformTimeIndexMetaData` storage
391
+ class, or route the storage-contract work to the MetaTable skill. When a
392
+ DataNode storage table needs a platform-managed FK, use
407
393
  `MetaTableForeignKey(TargetModel, column=...)` on the storage class. Do not use
408
394
  `ForeignKey(Target.__table__.c.uid)`, table fullnames, or explicit target UID
409
395
  maps in DataNode examples.
@@ -445,16 +431,14 @@ When reviewing an existing DataNode, look for:
445
431
  - hidden dependency creation inside `update()`
446
432
  - invalid identity-indexed output shape
447
433
  - `time_index` dtype that is not exactly `datetime64[ns, UTC]`
448
- - DataFrame columns that do not match the `PlatformTimeIndexMetaData` or
449
- `MigrationManagedTimeIndexMetaData` class
434
+ - DataFrame columns that do not match the `PlatformTimeIndexMetaData` class
450
435
 
451
436
  ## Validation Checklist
452
437
 
453
438
  Do not claim success until you have checked:
454
439
 
455
440
  - the relevant docs were read first
456
- - output storage is a `PlatformTimeIndexMetaData` or
457
- `MigrationManagedTimeIndexMetaData` class that the SDK can register
441
+ - output storage is a `PlatformTimeIndexMetaData` class that the SDK can register
458
442
  - storage has an intention-rich `__metatable_description__`
459
443
  - every storage column has an intention-rich `info.description`
460
444
  - the DataNode constructor requires `storage_table`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mainsequence-meta-tables
3
- description: Use this skill when the task is about defining, registering, querying, migrating, or reviewing Main Sequence MetaTables. This skill owns SQLAlchemy table contracts, backend-managed table registration, external table registration, client-defined MetaTable migration registries, governed compiled SQL operations, foreign keys, indexes, and validation rules. It does not own DataNode producers, API route contracts, scheduling, releases, or sharing policy.
3
+ description: Use this skill when the task is about defining, registering, querying, migrating, or reviewing Main Sequence MetaTables. This skill owns SQLAlchemy table contracts, backend-managed table registration, external table registration, Alembic-based MetaTable migrations, governed compiled SQL operations, foreign keys, indexes, and validation rules. It does not own DataNode producers, API route contracts, scheduling, releases, or sharing policy.
4
4
  ---
5
5
 
6
6
  # Main Sequence MetaTables
@@ -19,8 +19,8 @@ This skill is for schema-driven application tables registered through TS Manager
19
19
  - build registration requests from resolved SQLAlchemy metadata when inspection is useful
20
20
  - define indexes and foreign keys in the table contract
21
21
  - design governed compiled SQL read and write operations
22
- - design client-defined `MigrationMetaTable` registries for contract evolution
23
- - package SQL migrations and old/new contract hashes for backend apply
22
+ - design provider-based Alembic contract evolution for MetaTables
23
+ - run the documented `mainsequence migrations ...` lifecycle for Alembic-backed MetaTable changes
24
24
  - review table contracts for physical-name, namespace, and identifier issues
25
25
  - review whether a task should be a `MetaTable` or a `DataNode`
26
26
 
@@ -55,11 +55,12 @@ If the user is still in the discovery process and does not yet know what data ex
55
55
  ## Read First
56
56
 
57
57
  1. `docs/tutorial/working_with_meta_tables.md`
58
- 2. `docs/knowledge/meta_tables/index.md`
59
- 3. `docs/knowledge/meta_tables/sqlalchemy.md`
60
- 4. `docs/knowledge/meta_tables/compiled_sql.md`
61
- 5. `docs/knowledge/meta_tables/migrations.md`
62
- 6. `docs/knowledge/meta_tables/api.md`
58
+ 2. For migration work, `docs/tutorial/metatable_migrations.md`
59
+ 3. `docs/knowledge/meta_tables/index.md`
60
+ 4. `docs/knowledge/meta_tables/sqlalchemy.md`
61
+ 5. `docs/knowledge/meta_tables/compiled_sql.md`
62
+ 6. `docs/knowledge/meta_tables/migrations.md`
63
+ 7. `docs/knowledge/meta_tables/api.md`
63
64
 
64
65
  ## Inputs This Skill Needs
65
66
 
@@ -72,8 +73,9 @@ Before changing code, collect or infer:
72
73
  - expected mutation patterns
73
74
  - whether TS Manager should create the physical table
74
75
  - for `external_registered`, the target `DynamicTableDataSource` UID
75
- - for contract changes, the target migration registry MetaTable or registry class
76
- - for contract changes, the package, migration namespace, revision, parent revision, SQL file, affected table identifiers, and old/new SQLAlchemy contract declarations
76
+ - for contract changes, the selected `AlembicMetaTableMigration` provider or provider module path
77
+ - for contract changes, the provider's `AlembicVersionMetaTable` binding and whether it has been registered
78
+ - for contract changes, the intended Alembic revision, parent/current revision, target revision, and updated SQLAlchemy declarations
77
79
 
78
80
  If ownership of the physical table lifecycle is unclear, stop before choosing a management mode.
79
81
 
@@ -87,8 +89,9 @@ For every non-trivial task, decide:
87
89
  4. What namespace and identifier define the logical table identity?
88
90
  5. Are foreign-key dependencies aligned with registration order?
89
91
  6. What governed operations should be allowed by the declared table scope?
90
- 7. If the table already exists and its contract changes, is this a migration through a registry row rather than normal registration?
91
- 8. For a migration, what stable affected-table identifiers and old/new contract hashes will the backend validate?
92
+ 7. If the table already exists and its contract changes, is this an Alembic migration rather than normal registration?
93
+ 8. For a migration, which provider object controls `target_metadata`, `script_location`, `alembic_registry`, and `metatable_models`?
94
+ 9. For a migration, has the provider's Alembic version-table binding been registered?
92
95
 
93
96
  ## Build Rules
94
97
 
@@ -105,9 +108,9 @@ For `platform_managed`, inherit from `PlatformManagedMetaTable`.
105
108
  The mixin derives the SQLAlchemy physical table name from storage-relevant configuration and table shape. Do not hand-write `__tablename__` for normal backend-managed tables.
106
109
 
107
110
  When a platform-managed table must support in-place contract migrations from its
108
- first version, use `MigrationManagedMetaTable` instead. For time-indexed
109
- DataNode storage that must support in-place contract migrations, use
110
- `MigrationManagedTimeIndexMetaData`.
111
+ first version, use Alembic. Keep the SDK model as a normal
112
+ `PlatformManagedMetaTable` or `PlatformTimeIndexMetaData` catalog contract, and
113
+ apply physical schema changes through the Alembic migration workflow.
111
114
 
112
115
  Schema must come from SQLAlchemy table metadata, usually `__table_args__ = {"schema": "public"}` or the tuple form ending in `{"schema": ...}`. Do not add a separate MetaTable-specific schema attribute.
113
116
 
@@ -237,7 +240,11 @@ asset_request = external_registered_registration_request_from_sqlalchemy_model(
237
240
  asset_meta_table = MetaTable.register(asset_request)
238
241
  ```
239
242
 
240
- ### 4. Schema changes use a migration registry
243
+ ### 4. Schema changes use Alembic
244
+
245
+ When doing migration work, first read
246
+ `docs/tutorial/metatable_migrations.md`. That document is the tutorial source
247
+ for the provider-based Alembic lifecycle.
241
248
 
242
249
  Do not apply in-place contract changes by changing a `PlatformManagedMetaTable`
243
250
  SQLAlchemy class and calling normal registration again. Shape-addressed
@@ -245,73 +252,38 @@ SQLAlchemy class and calling normal registration again. Shape-addressed
245
252
  foreign keys, or constraints change, so new code cannot reliably recover the
246
253
  previous shape-derived table.
247
254
 
248
- For contract evolution, use `mainsequence.meta_tables.migrations`:
249
-
250
- - declare a client-owned `MigrationMetaTable` registry
251
- - load SQL and manifest files from the installed Python package
252
- - compute `manifest_sha256` and `sql_sha256`
253
- - compute `old_contract_hashes`, `new_contract_hashes`, and `new_contracts`
254
- from SQLAlchemy model declarations
255
- - sync the migration row into the registry MetaTable
256
- - call `MetaTable.apply_migration(...)` with a `metatable-migration.v1`
257
- request that references the registry row
258
-
259
- `migration_meta_table_uid` is the UID of the registry MetaTable that stores
260
- migration rows. It is not the UID of the table being migrated.
261
-
262
- Affected tables are resolved by stable logical identifiers:
263
-
264
- ```python
265
- affected_tables = [{"identifier": "sdk-examples.Asset"}]
266
- ```
267
-
268
- For a changed table, model the old and new contracts explicitly and keep the
269
- same `__metatable_identifier__` on both declarations:
270
-
271
- ```python
272
- from mainsequence.meta_tables import MigrationManagedMetaTable
273
-
274
-
275
- class AssetBeforeMigration(MigrationManagedMetaTable, BeforeBase):
276
- __metatable_namespace__ = "sdk-examples"
277
- __metatable_identifier__ = "sdk-examples.Asset"
278
-
279
- uid: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
280
- symbol: Mapped[str] = mapped_column(String(64), nullable=False)
281
-
282
-
283
- class AssetAfterMigration(MigrationManagedMetaTable, AfterBase):
284
- __metatable_namespace__ = "sdk-examples"
285
- __metatable_identifier__ = "sdk-examples.Asset"
286
-
287
- uid: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
288
- symbol: Mapped[str] = mapped_column(String(64), nullable=False)
289
- status: Mapped[str] = mapped_column(String(32), nullable=False)
255
+ For contract evolution, define or update one selected
256
+ `AlembicMetaTableMigration` provider:
257
+
258
+ - put the provider in `mainsequence_migrations.py:migration` or pass
259
+ `--provider module.path:migration`
260
+ - set `package`, `migration_namespace`, `script_location`, and `target_metadata`
261
+ - set `alembic_registry` to an `AlembicVersionMetaTable` subclass
262
+ - list the post-apply catalog scope in `metatable_models`
263
+ - generate, render, dry-run, apply, and optionally refresh catalog bindings
264
+ through `mainsequence migrations ...` commands
265
+
266
+ `alembic_version_meta_table_uid` is the UID of the catalog binding for Alembic's
267
+ version table. It is not the UID of the table being migrated.
268
+
269
+ Do not ask users to construct backend migration payloads, call low-level
270
+ migration request models, or use SDK helper functions directly. The backend
271
+ request shape is reference material in the tutorial; the user-facing path is:
272
+
273
+ ```bash
274
+ mainsequence migrations register-version-table --provider mainsequence_migrations:migration
275
+ mainsequence migrations revision --provider mainsequence_migrations:migration --autogenerate -m "change"
276
+ mainsequence migrations render --provider mainsequence_migrations:migration --to head
277
+ mainsequence migrations upgrade --provider mainsequence_migrations:migration --to head --dry-run
278
+ mainsequence migrations upgrade --provider mainsequence_migrations:migration --to head --apply --register-metatables
290
279
  ```
291
280
 
292
- Then package the migration row with both contract versions:
293
-
294
- ```python
295
- packaged = load_packaged_migration(
296
- "examples.meta_tables.migrations",
297
- "packaged/002_add_asset_status.yaml",
298
- old_contract_models={"sdk-examples.Asset": AssetBeforeMigration},
299
- new_contract_models={"sdk-examples.Asset": AssetAfterMigration},
300
- )
301
- ```
302
-
303
- The backend apply endpoint validates the old hash before SQL execution and the
304
- new hash after introspection/MetaTable refresh. The SDK must not send executable
305
- SQL directly in the apply request body; the backend reads SQL from the
306
- referenced registry row.
307
-
308
- For time-indexed DataNode storage, use `MigrationManagedTimeIndexMetaData`. It
309
- is a `MigrationManagedMetaTable` target for packaging and validation, but it
310
- keeps the `TimeIndexMetaData` registration endpoint, `time_index_name`,
311
- `index_names`, and time-indexed table contract.
281
+ The SQL must be Alembic-rendered from the selected provider. After SQL apply
282
+ succeeds, register or refresh only the application MetaTable catalog bindings
283
+ listed in `migration.metatable_models`.
312
284
 
313
- Use `examples/meta_tables/migrations/contract_hash_rotation.py` as the canonical
314
- example for a MetaTable contract change.
285
+ Do not use SDK-managed migration artifact tables, artifact sync helpers, or custom
286
+ `operations()` migration modules.
315
287
 
316
288
  ### 5. Governed operations declare scope
317
289
 
@@ -333,18 +305,16 @@ When reviewing an existing MetaTable workflow, look for:
333
305
  - missing `__metatable_description__`, or a description that only repeats column names instead of table intention
334
306
  - mapped columns without `info.label` and `info.description`
335
307
  - backend-managed models that do not inherit `PlatformManagedMetaTable`
336
- - migration-managed tables that should use `MigrationManagedMetaTable` or
337
- `MigrationManagedTimeIndexMetaData` from their first version
308
+ - schema changes that bypass Alembic or try to use SDK operation lists
309
+ - migration work that lacks a selected `AlembicMetaTableMigration` provider
338
310
  - backend-managed examples that use namespace environment variables instead of a plain `sdk-examples` namespace
339
311
  - duplicate schema sources outside SQLAlchemy table metadata
340
312
  - external tables registered with unstable physical names
341
313
  - platform-managed examples that manually sequence parent registration instead
342
314
  of relying on `MetaTableForeignKey(...)` recursive registration
343
315
  - external child registrations that do not map foreign-key targets to registered parent `MetaTable.uid` values
344
- - contract changes attempted through normal registration instead of a `MigrationMetaTable` registry row
345
- - migration apply requests that confuse `migration_meta_table_uid` with an affected table UID
346
- - migration rows missing old/new contract hashes for affected in-place tables
347
- - migration rows that include arbitrary SQL in the request body instead of packaged SQL in the registry row
316
+ - contract changes attempted through normal registration instead of an Alembic migration
317
+ - migration work that asks users to define backend payloads, artifact rows, or SDK request objects
348
318
  - compiled SQL operations without complete table scope
349
319
  - raw SQL that hardcodes stale physical names
350
320
  - a table that should really be modeled as a DataNode instead
@@ -362,10 +332,11 @@ Do not claim success until you have checked:
362
332
  - backend-managed physical names match the storage hash
363
333
  - registration returns a `MetaTable.uid`
364
334
  - compiled SQL operations declare table scope
365
- - migrations use a client-defined `MigrationMetaTable` registry
366
- - migration rows include stable affected table identifiers
367
- - migration rows include old/new contract hashes and post-migration contracts
368
- - migration apply/status helpers use typed `metatable-migration.v1` request and response models
335
+ - migrations use Alembic-rendered SQL
336
+ - migrations are scoped by an `AlembicMetaTableMigration` provider
337
+ - the provider's Alembic version-table binding is registered before apply/current
338
+ - post-apply catalog registration is scoped to `migration.metatable_models`
339
+ - user-facing migration instructions stay on the documented CLI/provider lifecycle
369
340
 
370
341
  For related tables, also check:
371
342
 
@@ -381,8 +352,8 @@ For related tables, also check:
381
352
  - the target data source is unknown for an `external_registered` workflow
382
353
  - the task really requires a time-series published table
383
354
  - the workflow requires direct database credentials outside TS Manager governance
384
- - a requested contract change lacks a stable affected table identifier or old contract anchor
385
- - the user expects the SDK to autogenerate migrations or parse arbitrary request-body SQL
355
+ - a requested contract change lacks a selected provider or registered Alembic version-table binding
356
+ - the user expects the SDK to invent schema changes without Alembic/provider metadata
386
357
  - the task is actually an API or orchestration problem
387
358
 
388
359
  Do not guess through registration or execution semantics.