mainsequence 4.3.9__tar.gz → 4.3.16__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.3.9/mainsequence.egg-info → mainsequence-4.3.16}/PKG-INFO +1 -1
- mainsequence-4.3.16/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +102 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +26 -20
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/migrations.py +125 -56
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/metatables/core.py +94 -251
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/data_nodes.py +24 -3
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/persist_managers.py +140 -29
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/run_operations.py +174 -41
- mainsequence-4.3.9/mainsequence/meta_tables/migrations.py → mainsequence-4.3.16/mainsequence/meta_tables/migrations/__init__.py +61 -42
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/alembic.py +165 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/env.py +119 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/provider.py +25 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/registry.py +75 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/scaffold.py +221 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/templates/__init__.py +1 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/templates/env.py.mako +8 -0
- mainsequence-4.3.16/mainsequence/meta_tables/migrations/templates/script.py.mako +28 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence.egg-info/SOURCES.txt +10 -1
- {mainsequence-4.3.9 → mainsequence-4.3.16}/pyproject.toml +2 -2
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_cli_migrations.py +58 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_data_node_update_flow.py +30 -1
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_meta_table_migrations.py +301 -15
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_meta_tables_client_models.py +4 -57
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_meta_tables_sqlalchemy_contracts.py +44 -2
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_run_configuration.py +2 -11
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_source_table_configuration.py +42 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_update_runner_uid_runtime.py +205 -1
- {mainsequence-4.3.9 → mainsequence-4.3.16}/LICENSE +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/README.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/__main__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/api.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/cli.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/config.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/base.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/client.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/defaults.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/logconf.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/setup.cfg +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_auth_precedence.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_cli.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_client.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_dependency_extras.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_filter_normalization.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_instrumentation.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_logconf.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_schema_names.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_secret_client_model.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_update_statistics.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_update_uid_guards.py +0 -0
- {mainsequence-4.3.9 → mainsequence-4.3.16}/tests/test_workspace_snapshot.py +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mainsequence-metatable-migrations
|
|
3
|
+
description: Use this skill when the task is about Main Sequence MetaTable schema evolution, Alembic provider setup, migration scaffold generation, revision creation, migration upgrade/current commands, provider-scoped MetaTable reservation/finalization, or debugging migration lifecycle failures. This skill owns the migration-first workflow for platform-managed MetaTables and should be used instead of direct MetaTable.register() guidance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Main Sequence MetaTable Migrations
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Use this skill for platform-managed MetaTable schema lifecycle work. The
|
|
11
|
+
standard path is migration-first: declare SQLAlchemy MetaTable models, put them
|
|
12
|
+
in a provider, run `mainsequence migrations ...`, and let the SDK reserve,
|
|
13
|
+
migrate, finalize, and bind provider-scoped MetaTables.
|
|
14
|
+
|
|
15
|
+
Do not recommend direct `MetaTable.register()` or model `.register()` calls for
|
|
16
|
+
platform-managed application tables outside the migration workflow.
|
|
17
|
+
|
|
18
|
+
## Read First
|
|
19
|
+
|
|
20
|
+
1. `docs/tutorial/metatable_migrations.md`
|
|
21
|
+
2. `docs/knowledge/meta_tables/migrations.md`
|
|
22
|
+
3. `docs/knowledge/meta_tables/api.md`
|
|
23
|
+
4. `docs/adr/0020-metatable-migration-artifact-registry.md`
|
|
24
|
+
5. `docs/adr/0026-sdk-owned-migration-scaffolding.md`
|
|
25
|
+
|
|
26
|
+
## Required Decisions
|
|
27
|
+
|
|
28
|
+
- Which provider module owns the migration stream?
|
|
29
|
+
- Which package and migration namespace identify the provider?
|
|
30
|
+
- Which `AlembicVersionMetaTable` binding points to Alembic's version table?
|
|
31
|
+
- Which SQLAlchemy `MetaData` object is the target metadata?
|
|
32
|
+
- Which provider-scoped MetaTable models belong in `metatable_models`?
|
|
33
|
+
- Does a dynamic provider need `metadata_for_models(...)` instead of full
|
|
34
|
+
package metadata?
|
|
35
|
+
- Does the project need an `after_register_metatables` catalog hook, and does
|
|
36
|
+
that hook use `context.metatable_models` and `context.registered_metatables`
|
|
37
|
+
instead of importing a broader registry?
|
|
38
|
+
|
|
39
|
+
## Standard Workflow
|
|
40
|
+
|
|
41
|
+
Use SDK-owned scaffold and helpers when creating a migration package:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
mainsequence migrations scaffold \
|
|
45
|
+
--package msm \
|
|
46
|
+
--module migrations \
|
|
47
|
+
--namespace mainsequence.examples \
|
|
48
|
+
--base msm.base:MarketsBase \
|
|
49
|
+
--metadata msm.base:MarketsBase.metadata
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The generated provider should use:
|
|
53
|
+
|
|
54
|
+
- `build_alembic_version_metatable(...)`
|
|
55
|
+
- `build_metatable_model_registry(...)`
|
|
56
|
+
- `build_metatable_migration_provider(...)`
|
|
57
|
+
- SDK-owned `run_mainsequence_alembic_env(...)`
|
|
58
|
+
- SDK-owned `script.py.mako`
|
|
59
|
+
|
|
60
|
+
Then use the normal lifecycle:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
mainsequence migrations current --provider migrations:migration
|
|
64
|
+
mainsequence migrations revision --provider migrations:migration
|
|
65
|
+
mainsequence migrations upgrade --provider migrations:migration head
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`revision` writes normal Alembic files. `upgrade` reserves provider MetaTables,
|
|
69
|
+
runs Alembic DDL through the backend-issued migration credential, finalizes
|
|
70
|
+
provider-scoped MetaTable catalog rows, and runs the optional provider hook.
|
|
71
|
+
|
|
72
|
+
## Rules
|
|
73
|
+
|
|
74
|
+
- Keep Alembic as the schema migration engine; do not build custom operation
|
|
75
|
+
lists or fake migration payload formats.
|
|
76
|
+
- Keep provider scope explicit. Do not scan all imported models or installed
|
|
77
|
+
packages.
|
|
78
|
+
- For one-model or configured dynamic providers, use `metadata_for_models(...)`
|
|
79
|
+
and a provider-specific `metatable_models` list.
|
|
80
|
+
- Never send or thread request-side `data_source_uid` through migration status
|
|
81
|
+
or apply flows. Backend migration operations resolve the data source from the
|
|
82
|
+
registered Alembic version MetaTable UID.
|
|
83
|
+
- Do not create SDK reset/reconcile commands for stale reserved state. If stale
|
|
84
|
+
reserved state exists, fail clearly and require an explicit backend/admin
|
|
85
|
+
repair path.
|
|
86
|
+
- Do not write direct backend migration request bodies in examples. Use the CLI
|
|
87
|
+
and SDK provider APIs.
|
|
88
|
+
- Do not call platform-managed model `.register()` in normal application code.
|
|
89
|
+
Registration is reserved for the migration workflow.
|
|
90
|
+
|
|
91
|
+
## Debugging
|
|
92
|
+
|
|
93
|
+
- If `current` fails before Alembic runs, inspect the provider import path and
|
|
94
|
+
Alembic version MetaTable binding.
|
|
95
|
+
- If `revision` autogenerate tries to create everything again, the local
|
|
96
|
+
migration connection cannot see the provider's current physical tables.
|
|
97
|
+
- If `upgrade` fails during prepare, inspect provider model identifiers,
|
|
98
|
+
physical table names, and reserved/active MetaTable rows.
|
|
99
|
+
- If `upgrade` fails during finalization, inspect whether Alembic created the
|
|
100
|
+
physical tables for every provider-scoped model.
|
|
101
|
+
- If an after-register hook reports the wrong model count, ensure it uses the
|
|
102
|
+
provider-scoped context, not a package-global model registry.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mainsequence-meta-tables
|
|
3
|
-
description: Use this skill when the task is about defining,
|
|
3
|
+
description: Use this skill when the task is about defining, querying, or reviewing Main Sequence MetaTables. This skill owns SQLAlchemy table contracts, backend-managed table authoring, external table registration, governed compiled SQL operations, foreign keys, indexes, naming, cadence, and validation rules. For Alembic migration lifecycle work, use the mainsequence-metatable-migrations skill. It does not own DataNode producers, API route contracts, scheduling, releases, or sharing policy.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Main Sequence MetaTables
|
|
@@ -15,12 +15,11 @@ This skill is for schema-driven application tables registered through TS Manager
|
|
|
15
15
|
|
|
16
16
|
- define SQLAlchemy/Core or ORM table models for `MetaTable` registration
|
|
17
17
|
- choose `platform_managed` or `external_registered` management mode
|
|
18
|
-
-
|
|
18
|
+
- declare platform-managed tables for migration-managed registration
|
|
19
19
|
- build registration requests from resolved SQLAlchemy metadata when inspection is useful
|
|
20
20
|
- define indexes and foreign keys in SQLAlchemy metadata for Alembic-owned DDL
|
|
21
21
|
- design governed compiled SQL read and write operations
|
|
22
|
-
-
|
|
23
|
-
- run the documented `mainsequence migrations ...` lifecycle for Alembic-backed MetaTable changes
|
|
22
|
+
- route provider-based Alembic contract evolution to the MetaTable migration skill
|
|
24
23
|
- review table contracts for physical-name, namespace, and identifier issues
|
|
25
24
|
- review whether a task should be a `MetaTable` or a `DataNode`
|
|
26
25
|
|
|
@@ -41,6 +40,8 @@ If the user is still in the discovery process and does not yet know what data ex
|
|
|
41
40
|
|
|
42
41
|
- discovery-only data inventory before table implementation:
|
|
43
42
|
`.agents/skills/mainsequence/data_access/exploration/SKILL.md`
|
|
43
|
+
- MetaTable migrations:
|
|
44
|
+
`.agents/skills/mainsequence/data_publishing/meta_table_migrations/SKILL.md`
|
|
44
45
|
- DataNodes:
|
|
45
46
|
`.agents/skills/mainsequence/data_publishing/data_nodes/SKILL.md`
|
|
46
47
|
- APIs and FastAPI:
|
|
@@ -55,7 +56,9 @@ If the user is still in the discovery process and does not yet know what data ex
|
|
|
55
56
|
## Read First
|
|
56
57
|
|
|
57
58
|
1. `docs/tutorial/working_with_meta_tables.md`
|
|
58
|
-
2. For migration work,
|
|
59
|
+
2. For migration work, use
|
|
60
|
+
`.agents/skills/mainsequence/data_publishing/meta_table_migrations/SKILL.md`
|
|
61
|
+
and `docs/tutorial/metatable_migrations.md`
|
|
59
62
|
3. `docs/knowledge/meta_tables/index.md`
|
|
60
63
|
4. `docs/knowledge/meta_tables/sqlalchemy.md`
|
|
61
64
|
5. `docs/knowledge/meta_tables/compiled_sql.md`
|
|
@@ -111,9 +114,9 @@ creation or deletion.
|
|
|
111
114
|
The only migration workflow to recommend is the Main Sequence CLI lifecycle:
|
|
112
115
|
|
|
113
116
|
```bash
|
|
114
|
-
mainsequence migrations current --provider
|
|
115
|
-
mainsequence migrations revision --provider
|
|
116
|
-
mainsequence migrations upgrade --provider
|
|
117
|
+
mainsequence migrations current --provider sdk_examples.migrations:migration
|
|
118
|
+
mainsequence migrations revision --provider sdk_examples.migrations:migration
|
|
119
|
+
mainsequence migrations upgrade --provider sdk_examples.migrations:migration head
|
|
117
120
|
```
|
|
118
121
|
|
|
119
122
|
### 1. SQLAlchemy metadata is the authoring source
|
|
@@ -279,7 +282,7 @@ both the schema and the table's intention.
|
|
|
279
282
|
Provider scope:
|
|
280
283
|
|
|
281
284
|
```python
|
|
282
|
-
migration =
|
|
285
|
+
migration = build_metatable_migration_provider(
|
|
283
286
|
...,
|
|
284
287
|
metatable_models=[Account, Asset],
|
|
285
288
|
)
|
|
@@ -304,9 +307,10 @@ asset_meta_table = MetaTable.register(asset_request)
|
|
|
304
307
|
|
|
305
308
|
### 4. Schema changes use Alembic
|
|
306
309
|
|
|
307
|
-
When doing migration work,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
+
When doing migration work, use
|
|
311
|
+
`.agents/skills/mainsequence/data_publishing/meta_table_migrations/SKILL.md`
|
|
312
|
+
and read `docs/tutorial/metatable_migrations.md`. The migration skill owns the
|
|
313
|
+
provider-based Alembic lifecycle.
|
|
310
314
|
|
|
311
315
|
Do not apply in-place contract changes by changing a `PlatformManagedMetaTable`
|
|
312
316
|
SQLAlchemy class and calling normal registration again. Shape-addressed
|
|
@@ -323,8 +327,10 @@ create a new Alembic revision on top of the current head.
|
|
|
323
327
|
For contract evolution, define or update one selected
|
|
324
328
|
`AlembicMetaTableMigration` provider:
|
|
325
329
|
|
|
326
|
-
-
|
|
327
|
-
|
|
330
|
+
- create or update a scaffolded package provider with
|
|
331
|
+
`mainsequence migrations scaffold`
|
|
332
|
+
- pass the selected provider explicitly, for example
|
|
333
|
+
`--provider sdk_examples.migrations:migration`
|
|
328
334
|
- set `package`, `migration_namespace`, `script_location`, and `target_metadata`
|
|
329
335
|
- set `alembic_registry` to an `AlembicVersionMetaTable` subclass
|
|
330
336
|
- list the post-apply catalog scope in `metatable_models`
|
|
@@ -343,14 +349,14 @@ a bare table name. Use `schema_table_name(app, concept, suffix=None)` for the
|
|
|
343
349
|
physical table and Alembic version table names. Use `suffix` for a namespace or
|
|
344
350
|
variant, for example `schema_table_name("msm", "positions", suffix="broker")`.
|
|
345
351
|
|
|
346
|
-
Do not ask users to construct backend migration payloads
|
|
347
|
-
migration request models
|
|
348
|
-
|
|
352
|
+
Do not ask users to construct backend migration payloads or call low-level
|
|
353
|
+
migration request models. The backend request shape is reference material in
|
|
354
|
+
the tutorial; the user-facing path is:
|
|
349
355
|
|
|
350
356
|
```bash
|
|
351
|
-
mainsequence migrations current --provider
|
|
352
|
-
mainsequence migrations revision --provider
|
|
353
|
-
mainsequence migrations upgrade --provider
|
|
357
|
+
mainsequence migrations current --provider sdk_examples.migrations:migration
|
|
358
|
+
mainsequence migrations revision --provider sdk_examples.migrations:migration
|
|
359
|
+
mainsequence migrations upgrade --provider sdk_examples.migrations:migration head
|
|
354
360
|
```
|
|
355
361
|
|
|
356
362
|
All migration commands prepare the provider, reserve provider-scoped
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
import json
|
|
5
5
|
import logging
|
|
6
|
+
import pathlib
|
|
6
7
|
import re
|
|
7
8
|
import sys
|
|
8
9
|
from collections.abc import Mapping, Sequence
|
|
@@ -23,6 +24,7 @@ from mainsequence.meta_tables.migrations import (
|
|
|
23
24
|
alembic_config_for_provider,
|
|
24
25
|
apply_mainsequence_migration_role,
|
|
25
26
|
load_alembic_metatable_migration_provider,
|
|
27
|
+
scaffold_migration_package,
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
migrations = typer.Typer(help="Alembic-owned MetaTable migration commands")
|
|
@@ -30,7 +32,8 @@ REGISTER_ENDPOINT = "/orm/api/ts_manager/meta_table/register/"
|
|
|
30
32
|
METATABLE_COLLECTION_ENDPOINT = "/orm/api/ts_manager/meta_table/"
|
|
31
33
|
DYNAMIC_TABLE_COLLECTION_ENDPOINT = "/orm/api/ts_manager/dynamic_table/"
|
|
32
34
|
FINALIZE_MANAGED_ENDPOINT = "/orm/api/ts_manager/meta_table/finalize-managed/"
|
|
33
|
-
|
|
35
|
+
DEFAULT_SCAFFOLD_PROJECT_ROOT = pathlib.Path(".")
|
|
36
|
+
DEFAULT_SCAFFOLD_SOURCE_ROOT = pathlib.Path("src")
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
class _AlembicOutput:
|
|
@@ -412,9 +415,22 @@ def _emit_metatable_reservation(model: type[Any], item: Any) -> None:
|
|
|
412
415
|
)
|
|
413
416
|
|
|
414
417
|
|
|
418
|
+
def _finalization_item_failed(item: Any) -> bool:
|
|
419
|
+
return (
|
|
420
|
+
_item_value(item, "provisioning_status") != "active"
|
|
421
|
+
or _item_value(item, "physical_table_exists") is False
|
|
422
|
+
or _item_value(item, "error") not in (None, "", {})
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
|
|
415
426
|
def _emit_metatable_finalization(model: type[Any], item: Any) -> None:
|
|
416
427
|
finalized = _item_value(item, "finalized")
|
|
417
|
-
|
|
428
|
+
if _finalization_item_failed(item):
|
|
429
|
+
action = "finalize-failed"
|
|
430
|
+
elif finalized is False:
|
|
431
|
+
action = "active"
|
|
432
|
+
else:
|
|
433
|
+
action = "finalized"
|
|
418
434
|
_emit_progress(
|
|
419
435
|
_metatable_message(
|
|
420
436
|
endpoint=FINALIZE_MANAGED_ENDPOINT,
|
|
@@ -666,6 +682,113 @@ def _next_sequential_revision_id(
|
|
|
666
682
|
return next_revision_id
|
|
667
683
|
|
|
668
684
|
|
|
685
|
+
@migrations.command("scaffold")
|
|
686
|
+
def scaffold(
|
|
687
|
+
package: str = typer.Option(
|
|
688
|
+
...,
|
|
689
|
+
"--package",
|
|
690
|
+
help="Project package or migration provider package name, for example msm.",
|
|
691
|
+
),
|
|
692
|
+
namespace: str = typer.Option(
|
|
693
|
+
...,
|
|
694
|
+
"--namespace",
|
|
695
|
+
help="Migration namespace for this provider.",
|
|
696
|
+
),
|
|
697
|
+
metadata: str = typer.Option(
|
|
698
|
+
...,
|
|
699
|
+
"--metadata",
|
|
700
|
+
help="Target SQLAlchemy metadata reference in module:object form.",
|
|
701
|
+
),
|
|
702
|
+
module: str = typer.Option(
|
|
703
|
+
"migrations",
|
|
704
|
+
"--module",
|
|
705
|
+
help="Python module to create, for example migrations or msm.migrations.",
|
|
706
|
+
),
|
|
707
|
+
project_root: pathlib.Path = typer.Option( # noqa: B008
|
|
708
|
+
DEFAULT_SCAFFOLD_PROJECT_ROOT,
|
|
709
|
+
"--project-root",
|
|
710
|
+
help="Project root where the source tree lives.",
|
|
711
|
+
),
|
|
712
|
+
source_root: pathlib.Path = typer.Option( # noqa: B008
|
|
713
|
+
DEFAULT_SCAFFOLD_SOURCE_ROOT,
|
|
714
|
+
"--source-root",
|
|
715
|
+
help="Source root under project root.",
|
|
716
|
+
),
|
|
717
|
+
base: str | None = typer.Option(
|
|
718
|
+
None,
|
|
719
|
+
"--base",
|
|
720
|
+
help="Optional project declarative base reference in module:object form.",
|
|
721
|
+
),
|
|
722
|
+
models: str | None = typer.Option(
|
|
723
|
+
None,
|
|
724
|
+
"--models",
|
|
725
|
+
help="Optional model registry function reference in module:object form.",
|
|
726
|
+
),
|
|
727
|
+
alembic_version_name: str = typer.Option(
|
|
728
|
+
"ProjectAlembicVersion",
|
|
729
|
+
"--alembic-version-name",
|
|
730
|
+
help="Generated Alembic version MetaTable class name.",
|
|
731
|
+
),
|
|
732
|
+
alembic_version_identifier: str | None = typer.Option(
|
|
733
|
+
None,
|
|
734
|
+
"--alembic-version-identifier",
|
|
735
|
+
help="Generated Alembic version MetaTable identifier.",
|
|
736
|
+
),
|
|
737
|
+
alembic_version_schema: str | None = typer.Option(
|
|
738
|
+
"public",
|
|
739
|
+
"--alembic-version-schema",
|
|
740
|
+
help="Physical schema for the Alembic version table. Pass an empty string for no schema.",
|
|
741
|
+
),
|
|
742
|
+
alembic_version_table_name: str = typer.Option(
|
|
743
|
+
"alembic_version",
|
|
744
|
+
"--alembic-version-table-name",
|
|
745
|
+
help="Physical Alembic version table name.",
|
|
746
|
+
),
|
|
747
|
+
force: bool = typer.Option(
|
|
748
|
+
False,
|
|
749
|
+
"--force",
|
|
750
|
+
help="Overwrite changed scaffold files.",
|
|
751
|
+
),
|
|
752
|
+
json_output: bool = typer.Option(False, "--json", help="Emit JSON."),
|
|
753
|
+
) -> None:
|
|
754
|
+
"""Create an SDK-shaped MetaTable migration package skeleton."""
|
|
755
|
+
|
|
756
|
+
normalized_schema = alembic_version_schema
|
|
757
|
+
if normalized_schema == "":
|
|
758
|
+
normalized_schema = None
|
|
759
|
+
try:
|
|
760
|
+
result = scaffold_migration_package(
|
|
761
|
+
project_root=project_root,
|
|
762
|
+
module=module,
|
|
763
|
+
package=package,
|
|
764
|
+
namespace=namespace,
|
|
765
|
+
metadata_ref=metadata,
|
|
766
|
+
base_ref=base,
|
|
767
|
+
model_registry_ref=models,
|
|
768
|
+
alembic_version_name=alembic_version_name,
|
|
769
|
+
alembic_version_identifier=alembic_version_identifier,
|
|
770
|
+
alembic_version_schema=normalized_schema,
|
|
771
|
+
alembic_version_table_name=alembic_version_table_name,
|
|
772
|
+
source_root=source_root,
|
|
773
|
+
force=force,
|
|
774
|
+
)
|
|
775
|
+
except (FileExistsError, ValueError) as exc:
|
|
776
|
+
raise typer.BadParameter(str(exc)) from exc
|
|
777
|
+
|
|
778
|
+
for file in result.files:
|
|
779
|
+
_emit_status(f"Scaffold {file.action} {file.path}")
|
|
780
|
+
_emit(
|
|
781
|
+
{
|
|
782
|
+
"root": str(result.root),
|
|
783
|
+
"files": [
|
|
784
|
+
{"path": str(file.path), "action": file.action}
|
|
785
|
+
for file in result.files
|
|
786
|
+
],
|
|
787
|
+
},
|
|
788
|
+
json_output=json_output,
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
|
|
669
792
|
@migrations.command("current")
|
|
670
793
|
def current(
|
|
671
794
|
provider: str | None = typer.Option(
|
|
@@ -884,57 +1007,3 @@ def downgrade(
|
|
|
884
1007
|
},
|
|
885
1008
|
json_output=json_output,
|
|
886
1009
|
)
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
@migrations.command("reset")
|
|
890
|
-
def reset(
|
|
891
|
-
provider: str | None = typer.Option(
|
|
892
|
-
None,
|
|
893
|
-
"--provider",
|
|
894
|
-
help="Migration provider reference, for example msm.migrations:migration.",
|
|
895
|
-
),
|
|
896
|
-
confirm_reset: bool = typer.Option(
|
|
897
|
-
False,
|
|
898
|
-
"--confirm-reset",
|
|
899
|
-
help="Required confirmation for destructive provider-scoped reset.",
|
|
900
|
-
),
|
|
901
|
-
drop_physical_tables: bool = typer.Option(
|
|
902
|
-
True,
|
|
903
|
-
"--drop-physical-tables/--keep-physical-tables",
|
|
904
|
-
help="Drop provider physical tables during reset.",
|
|
905
|
-
),
|
|
906
|
-
clear_alembic_version_table: bool = typer.Option(
|
|
907
|
-
True,
|
|
908
|
-
"--clear-alembic-version-table/--keep-alembic-version-table",
|
|
909
|
-
help="Clear the provider Alembic version table during reset.",
|
|
910
|
-
),
|
|
911
|
-
include_reserved: bool = typer.Option(
|
|
912
|
-
True,
|
|
913
|
-
"--include-reserved/--active-only",
|
|
914
|
-
help="Include already-reserved provider MetaTables in reset results.",
|
|
915
|
-
),
|
|
916
|
-
timeout: float | None = typer.Option(None, "--timeout"),
|
|
917
|
-
json_output: bool = typer.Option(False, "--json", help="Emit JSON."),
|
|
918
|
-
) -> None:
|
|
919
|
-
"""Reset an Alembic-managed provider catalog/physical state."""
|
|
920
|
-
|
|
921
|
-
if not confirm_reset:
|
|
922
|
-
raise typer.BadParameter(
|
|
923
|
-
"Pass --confirm-reset to call the destructive provider reset endpoint.",
|
|
924
|
-
param_hint="--confirm-reset",
|
|
925
|
-
)
|
|
926
|
-
migration = _load_migration(provider)
|
|
927
|
-
_emit_status(
|
|
928
|
-
"Calling provider reset endpoint "
|
|
929
|
-
f"{ALEMBIC_PROVIDER_RESET_ENDPOINT} provider={migration.migration_provider_key}..."
|
|
930
|
-
)
|
|
931
|
-
response = migration.reset_alembic_provider(
|
|
932
|
-
confirm_reset=True,
|
|
933
|
-
drop_physical_tables=drop_physical_tables,
|
|
934
|
-
clear_alembic_version_table=clear_alembic_version_table,
|
|
935
|
-
include_reserved=include_reserved,
|
|
936
|
-
timeout=timeout,
|
|
937
|
-
on_reset_status=_emit_status,
|
|
938
|
-
)
|
|
939
|
-
_emit_status("Alembic provider reset finished.")
|
|
940
|
-
_emit(response, json_output=json_output)
|