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.
- {mainsequence-4.1.16/mainsequence.egg-info → mainsequence-4.1.18}/PKG-INFO +2 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +19 -35
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +63 -92
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/api.py +34 -34
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/cli.py +9 -3
- mainsequence-4.1.18/mainsequence/cli/migrations.py +370 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/__init__.py +1 -1
- mainsequence-4.1.18/mainsequence/client/metatables/__init__.py +36 -0
- mainsequence-4.1.16/mainsequence/client/models_metatables.py → mainsequence-4.1.18/mainsequence/client/metatables/core.py +7 -278
- mainsequence-4.1.18/mainsequence/client/metatables/migrations.py +152 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_foundry.py +9 -6
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_helpers.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/__init__.py +43 -11
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/compiled_sql/v1.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/build_operations.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/data_nodes.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/persist_managers.py +3 -1
- mainsequence-4.1.18/mainsequence/meta_tables/migrations.py +594 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/sqlalchemy_contracts.py +33 -194
- {mainsequence-4.1.16 → mainsequence-4.1.18/mainsequence.egg-info}/PKG-INFO +2 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/SOURCES.txt +5 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/requires.txt +1 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/pyproject.toml +2 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_build_operations_hashing.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_cli.py +38 -22
- mainsequence-4.1.18/tests/test_cli_migrations.py +338 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_node_storage_dimension_queries.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_node_update_flow.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_dependency_extras.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_duckdb_interface_dimensions.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_filter_normalization.py +12 -12
- mainsequence-4.1.18/tests/test_meta_table_migrations.py +457 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_meta_tables_client_models.py +40 -87
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_meta_tables_sqlalchemy_contracts.py +80 -113
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_pod_project_resolution.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_run_configuration.py +5 -5
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_source_table_configuration.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_sqlite_interface_dimensions.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_runner_uid_runtime.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_statistics.py +1 -1
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_update_uid_guards.py +1 -1
- mainsequence-4.1.16/mainsequence/meta_tables/migrations.py +0 -745
- mainsequence-4.1.16/tests/test_meta_table_migrations.py +0 -443
- {mainsequence-4.1.16 → mainsequence-4.1.18}/LICENSE +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/README.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/__main__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/config.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/base.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/client.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/defaults.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/logconf.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/setup.cfg +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_auth_precedence.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_client.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_logconf.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.1.16 → mainsequence-4.1.18}/tests/test_secret_client_model.py +0 -0
- {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.
|
|
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
|
|
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
|
|
14
|
-
|
|
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
|
|
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`
|
|
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
|
|
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()`
|
|
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__
|
|
226
|
-
|
|
227
|
-
|
|
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
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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`
|
|
404
|
-
|
|
405
|
-
storage
|
|
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`
|
|
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`
|
|
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,
|
|
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
|
|
23
|
-
-
|
|
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/
|
|
59
|
-
3. `docs/knowledge/meta_tables/
|
|
60
|
-
4. `docs/knowledge/meta_tables/
|
|
61
|
-
5. `docs/knowledge/meta_tables/
|
|
62
|
-
6. `docs/knowledge/meta_tables/
|
|
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
|
|
76
|
-
- for contract changes, the
|
|
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
|
|
91
|
-
8. For a migration,
|
|
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
|
|
109
|
-
|
|
110
|
-
|
|
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
|
|
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,
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
-
|
|
252
|
-
|
|
253
|
-
-
|
|
254
|
-
|
|
255
|
-
-
|
|
256
|
-
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
`
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
314
|
-
|
|
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
|
-
-
|
|
337
|
-
|
|
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
|
|
345
|
-
- migration
|
|
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
|
|
366
|
-
-
|
|
367
|
-
-
|
|
368
|
-
-
|
|
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
|
|
385
|
-
- the user expects the SDK to
|
|
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.
|