mainsequence 4.3.14__tar.gz → 4.3.19__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 (138) hide show
  1. {mainsequence-4.3.14/mainsequence.egg-info → mainsequence-4.3.19}/PKG-INFO +1 -1
  2. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +54 -31
  3. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/app_components/SKILL.md +70 -35
  4. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/metatables/core.py +69 -1
  5. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/data_nodes.py +25 -4
  6. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/persist_managers.py +140 -18
  7. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/run_operations.py +174 -41
  8. {mainsequence-4.3.14 → mainsequence-4.3.19/mainsequence.egg-info}/PKG-INFO +1 -1
  9. {mainsequence-4.3.14 → mainsequence-4.3.19}/pyproject.toml +1 -1
  10. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_data_node_storage_dimension_queries.py +75 -0
  11. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_meta_tables_sqlalchemy_contracts.py +44 -2
  12. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_run_configuration.py +128 -0
  13. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_update_runner_uid_runtime.py +205 -1
  14. {mainsequence-4.3.14 → mainsequence-4.3.19}/LICENSE +0 -0
  15. {mainsequence-4.3.14 → mainsequence-4.3.19}/README.md +0 -0
  16. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/AGENTS.md +0 -0
  17. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
  18. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  19. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  20. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  21. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  22. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  23. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  24. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  25. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  26. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  27. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  28. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  29. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  30. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  31. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  32. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  33. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  34. {mainsequence-4.3.14 → mainsequence-4.3.19}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  35. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/__init__.py +0 -0
  36. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/__main__.py +0 -0
  37. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/bootstrap.py +0 -0
  38. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/__init__.py +0 -0
  39. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/api.py +0 -0
  40. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/browser_auth.py +0 -0
  41. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/cli.py +0 -0
  42. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/config.py +0 -0
  43. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/docker_utils.py +0 -0
  44. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/doctor.py +0 -0
  45. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/local_ops.py +0 -0
  46. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/migrations.py +0 -0
  47. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/model_filters.py +0 -0
  48. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/project_status.py +0 -0
  49. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/pydantic_cli.py +0 -0
  50. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/sdk_utils.py +0 -0
  51. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/ssh_utils.py +0 -0
  52. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/cli/ui.py +0 -0
  53. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/__init__.py +0 -0
  54. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/agent_runtime_models.py +0 -0
  55. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/base.py +0 -0
  56. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/client.py +0 -0
  57. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/__init__.py +0 -0
  58. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/app_component.py +0 -0
  59. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/connections.py +0 -0
  60. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/data_models.py +0 -0
  61. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/workspace.py +0 -0
  62. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  63. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/compute_validation.py +0 -0
  64. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  65. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  66. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  67. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  68. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/dtype_codec.py +0 -0
  69. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/exceptions.py +0 -0
  70. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/fastapi/__init__.py +0 -0
  71. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/fastapi/auth.py +0 -0
  72. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/metatables/__init__.py +0 -0
  73. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/models_foundry.py +0 -0
  74. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/models_helpers.py +0 -0
  75. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/models_user.py +0 -0
  76. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/client/utils.py +0 -0
  77. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/defaults.py +0 -0
  78. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/instrumentation/__init__.py +0 -0
  79. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/instrumentation/utils.py +0 -0
  80. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/logconf.py +0 -0
  81. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/__init__.py +0 -0
  82. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/__main__.py +0 -0
  83. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  84. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  85. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  86. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  87. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  88. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  89. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  90. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/future_registry.py +0 -0
  91. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/hashing.py +0 -0
  92. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  93. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  94. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/env.py +0 -0
  95. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/provider.py +0 -0
  96. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/registry.py +0 -0
  97. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  98. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  99. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  100. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  101. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  102. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/schema_names.py +0 -0
  103. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  104. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence/runtime_flags.py +0 -0
  105. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence.egg-info/SOURCES.txt +0 -0
  106. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence.egg-info/dependency_links.txt +0 -0
  107. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence.egg-info/entry_points.txt +0 -0
  108. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence.egg-info/requires.txt +0 -0
  109. {mainsequence-4.3.14 → mainsequence-4.3.19}/mainsequence.egg-info/top_level.txt +0 -0
  110. {mainsequence-4.3.14 → mainsequence-4.3.19}/setup.cfg +0 -0
  111. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_auth_precedence.py +0 -0
  112. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_build_operations_hashing.py +0 -0
  113. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_cli.py +0 -0
  114. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_cli_browser_auth.py +0 -0
  115. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_cli_migrations.py +0 -0
  116. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_client.py +0 -0
  117. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_command_center_app_component_models.py +0 -0
  118. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_command_center_data_models.py +0 -0
  119. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_command_center_models.py +0 -0
  120. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  121. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_data_node_update_flow.py +0 -0
  122. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_dependency_extras.py +0 -0
  123. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_duckdb_interface_dimensions.py +0 -0
  124. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_filter_normalization.py +0 -0
  125. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_instrumentation.py +0 -0
  126. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_logconf.py +0 -0
  127. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_meta_table_migrations.py +0 -0
  128. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_meta_tables_client_models.py +0 -0
  129. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_models_user_request_bound_auth.py +0 -0
  130. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_pod_project_resolution.py +0 -0
  131. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_project_batch_jobs_from_file.py +0 -0
  132. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_schema_names.py +0 -0
  133. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_secret_client_model.py +0 -0
  134. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_source_table_configuration.py +0 -0
  135. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_sqlite_interface_dimensions.py +0 -0
  136. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_update_statistics.py +0 -0
  137. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_update_uid_guards.py +0 -0
  138. {mainsequence-4.3.14 → mainsequence-4.3.19}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.3.14
3
+ Version: 4.3.19
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
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: command-center-adapter-from-api
3
- description: Use when building or changing an API so Command Center can consume it through an Adapter from API connection. This skill defines the provider-side API contract standards required for Command Center connection discovery, health checks, operation selection, config fields, secret injection metadata, canonical `TabularFrameResponse` outputs, and tabular response mappings. It does not define general API architecture and does not imply the API may only serve these endpoints.
3
+ description: Use when building or changing an API so Command Center can consume it through an Adapter from API connection. This skill defines the provider-side API contract standards required for Command Center connection discovery, health checks, operation selection, config fields, secret injection metadata, canonical `TabularFrameResponse` outputs, and optional response-mapping metadata for frontend/editor context or future explicit transforms. It does not define general API architecture and does not imply the API may only serve these endpoints.
4
4
  ---
5
5
 
6
6
  # Command Center Adapter From API
@@ -13,7 +13,7 @@ connection.
13
13
  This skill defines the Command Center-facing contract that the API must expose. It does not own the
14
14
  whole API architecture. An API may serve other clients and routes, but if it is consumed by Command
15
15
  Center through this adapter, it must also expose the discovery, health, operation, config, secret,
16
- and response-mapping metadata described here.
16
+ and any optional response-mapping metadata described here.
17
17
 
18
18
  The runtime flow is:
19
19
 
@@ -26,8 +26,12 @@ API with Command Center contract endpoints
26
26
  ```
27
27
 
28
28
  Generic table, chart, statistic, curve, transform, and agent-facing data consumers must consume
29
- `core.tabular_frame@v1`. API responses that are provider-native, paginated, nested, or domain
30
- specific need an exact response mapping before they are consumed by generic tabular widgets.
29
+ an actual `core.tabular_frame@v1` payload at the consumption boundary. API responses that are
30
+ provider-native, paginated, nested, or domain specific are still provider-native even when the
31
+ contract includes `responseMappings`. A mapping may describe how a response could be interpreted by
32
+ frontend/editor tooling or a future explicit transform, but the current backend adapter must not
33
+ hot-path validate, extract JSONPath rows, coerce schemas, or reshape provider responses because a
34
+ mapping exists.
31
35
 
32
36
  ## Scope
33
37
 
@@ -39,7 +43,7 @@ This skill owns:
39
43
  - operation metadata needed by Connection Query
40
44
  - public config variable definitions
41
45
  - secret variable definitions and backend injection metadata
42
- - response mappings for canonical tabular consumption
46
+ - optional response-mapping metadata for frontend/editor context and future explicit transforms
43
47
  - API-side validation and maintenance rules for this contract
44
48
 
45
49
  This skill does not own:
@@ -103,7 +107,7 @@ GET /openapi.json
103
107
  ```
104
108
 
105
109
  This is supplementary metadata. The well-known Command Center contract decides what operations,
106
- config fields, secrets, and response mappings Command Center may use.
110
+ config fields, secrets, and optional response-mapping metadata Command Center may use.
107
111
 
108
112
  ### 3. Dedicated Health Endpoint
109
113
 
@@ -123,8 +127,9 @@ parameters. Do not use a parameterized data endpoint as a fake health check.
123
127
  Each queryable API operation must have a stable `operationId` in the well-known contract and a
124
128
  matching route in the API.
125
129
 
126
- Operation endpoints may return provider-native JSON. For generic tabular consumers, the contract
127
- must declare exactly how that response becomes `core.tabular_frame@v1`.
130
+ Operation endpoints may return a full canonical `core.tabular_frame@v1` payload or provider-native
131
+ JSON. `responseMappings` may document an intended tabular interpretation, but they are not a
132
+ runtime guarantee that provider-native JSON becomes `core.tabular_frame@v1`.
128
133
 
129
134
  ## Well-Known Contract Shape
130
135
 
@@ -185,7 +190,7 @@ Every operation listed in `availableOperations` must define:
185
190
  - `supportsMaxRows`
186
191
  - `parameters`
187
192
  - optional `requestBody`
188
- - `responseMappings`
193
+ - optional `responseMappings`
189
194
  - `cache`
190
195
 
191
196
  Rules:
@@ -264,8 +269,8 @@ from mainsequence.client.command_center.data_models import TabularFrameResponse
264
269
  Declare `response_model=TabularFrameResponse` instead of recreating the canonical frame shape
265
270
  locally.
266
271
 
267
- If an operation returns provider-native JSON, declare a `responseMappings` entry that exposes the
268
- operation as `core.tabular_frame@v1`:
272
+ If an operation returns provider-native JSON, it may declare a `responseMappings` entry that
273
+ describes a tabular interpretation for frontend/editor metadata or future explicit transforms:
269
274
 
270
275
  ```json
271
276
  {
@@ -289,13 +294,23 @@ operation as `core.tabular_frame@v1`:
289
294
 
290
295
  Rules:
291
296
 
292
- - `contract` must be `core.tabular_frame@v1` for generic tabular consumption.
293
- - `rowsPath` must point to the array of row objects inside the operation response.
294
- - `fieldTypes` must cover the fields that consumers need for formatting and inference.
295
- - Time-series metadata should be present when the rows are meant for charts, curves, or time-aware
297
+ - `responseMappings` are optional metadata in the current Adapter from API flow.
298
+ - A mapping does not make provider-native JSON a `core.tabular_frame@v1` runtime payload.
299
+ - The backend must not hot-path validate the upstream body against `responseMappings`.
300
+ - The backend must not extract JSONPath rows, coerce schemas, or reshape the response merely
301
+ because a mapping exists.
302
+ - If a mapping describes tabular interpretation, `contract` should be `core.tabular_frame@v1`.
303
+ - If `rowsPath` is present, it should point to the array of row objects inside the operation
304
+ response.
305
+ - If `fieldTypes` is present, it should cover the fields that frontend/editor tooling or future
306
+ transforms need for formatting and inference.
307
+ - Time-series metadata is useful when the mapped rows are meant for charts, curves, or time-aware
296
308
  transforms.
297
309
  - If the response shape changes, update the response mapping in the same change.
298
- - Do not bind provider-native JSON directly to generic tabular consumers.
310
+ - Do not claim provider-native JSON is safe for generic tabular consumers just because a
311
+ `responseMappings` entry exists.
312
+ - If generic tabular widgets need to consume the operation directly today, return
313
+ `TabularFrameResponse` from the API operation.
299
314
 
300
315
  ## Canonical SDK Model
301
316
 
@@ -313,8 +328,9 @@ Related SDK models:
313
328
  - `TabularTimeSeriesMetaResponse`
314
329
 
315
330
  Use these models when the API operation returns the full canonical frame. If the provider operation
316
- returns provider-native JSON instead, keep the provider response model explicit and declare an exact
317
- `responseMappings` entry that maps it into `core.tabular_frame@v1`.
331
+ returns provider-native JSON instead, keep the provider response model explicit. Add
332
+ `responseMappings` only as metadata; do not treat it as runtime conversion into
333
+ `core.tabular_frame@v1`.
318
334
 
319
335
  ## Required Decisions
320
336
 
@@ -327,9 +343,10 @@ Before implementing or revising an API for Adapter from API consumption, decide:
327
343
  5. Which operation IDs must remain stable?
328
344
  6. Which public config fields does the connection need?
329
345
  7. Which secrets does the connection need, and how does the backend inject them?
330
- 8. Which operations produce generic tabular consumption?
331
- 9. For each tabular operation, does the API return a full `core.tabular_frame@v1` document or a
332
- provider-native response with an exact `responseMappings` entry?
346
+ 8. Which operations directly return a full `core.tabular_frame@v1` payload for generic tabular
347
+ consumption?
348
+ 9. For provider-native responses, is optional `responseMappings` metadata useful, and what explicit
349
+ transform or future feature would consume it?
333
350
  10. If the operation returns a full canonical frame, does it use `TabularFrameResponse` as the
334
351
  FastAPI `response_model`?
335
352
 
@@ -343,7 +360,8 @@ For a FastAPI provider:
343
360
  - expose a zero-argument health route
344
361
  - expose query operation routes with documented request parameters
345
362
  - declare every Command Center-callable operation in `availableOperations`
346
- - declare `core.tabular_frame@v1` response mappings for tabular consumption
363
+ - declare `responseMappings` only as optional metadata when useful; do not rely on them for runtime
364
+ normalization
347
365
  - use `TabularFrameResponse` when an operation returns the full canonical frame
348
366
  - keep the API root, well-known contract, and OpenAPI document internally consistent
349
367
 
@@ -358,10 +376,11 @@ When reviewing an Adapter from API provider change, look for:
358
376
  - operations missing from `availableOperations`
359
377
  - operations exposed to Command Center without explicit allowlist metadata
360
378
  - secret values represented as public config or query payload fields
361
- - tabular responses without `core.tabular_frame@v1` response mappings
362
- - response mappings whose `rowsPath` no longer matches the API response
363
- - missing `fieldTypes` for fields consumed by widgets
364
- - API endpoints returning provider-native JSON directly to generic tabular consumers
379
+ - provider-native responses being treated as `core.tabular_frame@v1` because a mapping exists
380
+ - response mappings whose `rowsPath` no longer matches the API response when the mapping is present
381
+ - missing `fieldTypes` for fields that declared mappings or future transforms need
382
+ - API endpoints returning provider-native JSON directly to generic tabular consumers without an
383
+ explicit transform path
365
384
  - full canonical frame endpoints that do not use `TabularFrameResponse`
366
385
  - docs or README examples that disagree with the actual contract endpoint
367
386
 
@@ -380,10 +399,12 @@ Do not claim the API is consumable by Adapter from API until:
380
399
  - query-capable operations are explicitly marked as query-capable
381
400
  - public config and secret fields are separated
382
401
  - secret injection rules are backend-owned and explicit
383
- - each generic tabular operation declares `core.tabular_frame@v1`
402
+ - each operation that must feed generic tabular consumers directly returns `core.tabular_frame@v1`
384
403
  - each full canonical frame operation uses `TabularFrameResponse`
385
- - each provider-native tabular response has an exact `rowsPath`
386
- - field types and time-series hints are present where consumers need them
404
+ - provider-native responses are not represented as direct generic tabular outputs solely through
405
+ `responseMappings`
406
+ - optional response mappings, when present, have accurate `rowsPath`, `fieldTypes`, and time-series
407
+ hints for their intended metadata or transform use
387
408
  - the local README documents the Command Center contract endpoints
388
409
  - any general FastAPI/API work has also followed `application_surfaces/api_surfaces`
389
410
 
@@ -396,8 +417,10 @@ Stop and surface the missing backend task when:
396
417
  - operation IDs cannot be made stable
397
418
  - auth requirements are unknown
398
419
  - secret injection cannot be described without exposing secret values
399
- - no exact response mapping exists for generic tabular consumption
400
- - the API response shape cannot be mapped to `core.tabular_frame@v1`
420
+ - a provider-native response is being treated as generic tabular output only because
421
+ `responseMappings` exists
422
+ - the API response shape must feed generic tabular consumers directly but cannot return
423
+ `TabularFrameResponse`
401
424
  - a full canonical frame endpoint cannot import or use `TabularFrameResponse`
402
425
  - backend Adapter from API runtime support is required but not implemented
403
426
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: command-center-app-components
3
- description: Use this skill when the task is about AppComponent widgets in a Main Sequence project. This skill owns AppComponent input contracts, custom forms, form sections and field definitions, and the boundary between AppComponent input contracts and widget-facing output contracts, including requiring generic tabular consumers to receive core.tabular_frame@v1 instead of ad hoc AppComponent JSON. Before changing AppComponent payloads or contracts, verify the target widget in the Command Center registry through the CLI. Source order is strict: registry detail first, SDK client models second, local Main Sequence repository docs/models third only if the first two still leave something unresolved. Main Sequence is platform-first: if an AppComponent depends on a project API, that API must already exist as a FastAPI project resource and have a corresponding FastAPI ResourceRelease before the AppComponent is considered usable from Command Center. Resource and release creation belong to the orchestration-and-releases skill. It does not own workspace layout, generic FastAPI design, or Streamlit dashboards.
3
+ description: Use this skill when the task is about AppComponent widgets in a Main Sequence project. This skill owns AppComponent generated request forms, response-side editable-form and notification UI contracts, dynamic request/response binding contracts, and the boundary between AppComponent responses and widget-facing output contracts, including requiring generic tabular consumers to receive core.tabular_frame@v1 instead of ad hoc AppComponent JSON. Before changing AppComponent payloads or contracts, verify the target widget in the Command Center registry through the CLI. Source order is strict: registry detail first, SDK client models second, local Main Sequence repository docs/models third only if the first two still leave something unresolved. Main Sequence is platform-first: if an AppComponent depends on a project API, that API must already exist as a FastAPI project resource and have a corresponding FastAPI ResourceRelease before the AppComponent is considered usable from Command Center. Resource and release creation belong to the orchestration-and-releases skill. It does not own workspace layout, generic FastAPI design, or Streamlit dashboards.
4
4
  ---
5
5
 
6
6
  # Command Center AppComponents
@@ -11,22 +11,23 @@ Use this skill when the task is about the backend contract behind a Command Cent
11
11
 
12
12
  This skill is for:
13
13
 
14
- - AppComponent input contracts
15
- - custom forms
14
+ - AppComponent generated request form contracts
15
+ - response-side editable form and notification contracts
16
16
  - field and section definitions
17
- - deciding when default argument resolution is enough
17
+ - deciding when default request form generation is enough
18
18
  - deciding when a widget-facing API response must use an exact SDK contract
19
19
  - requiring API-backed AppComponents to depend on deployed FastAPI resources/releases, not local-only API code
20
20
 
21
21
  ## This Skill Can Do
22
22
 
23
- - decide whether an AppComponent should rely on the default generated form
24
- - create a custom `EditableFormDefinition`
23
+ - decide whether an AppComponent should rely on the default generated request form
24
+ - return an `EditableFormDefinition` response when the API should render a stateful editable response form
25
+ - return a `NotificationDefinition` response when the API should render banner-style feedback
25
26
  - define `FormSectionDefinition`
26
27
  - define `FormFieldDefinition`
27
28
  - choose the correct `FormFieldKind`
28
29
  - define stable `token` values for fields
29
- - review whether an AppComponent form is too thin or too custom
30
+ - review whether the request form or response UI contract is over- or under-specified
30
31
  - separate input contracts from output contracts
31
32
  - decide when the API behind an AppComponent must return exact widget-facing response models
32
33
  - verify the target widget type in the CLI registry before changing payload or contract logic
@@ -90,8 +91,10 @@ Before changing an AppComponent backend contract, collect or infer:
90
91
  - registry detail payload from:
91
92
  - `mainsequence cc registered_widget_type detail <WIDGET_ID> --json`
92
93
  - what the widget is trying to collect from the user
93
- - whether the default generated form is already sufficient
94
- - the fields, sections, and labels the form should expose
94
+ - whether the default generated request form is already sufficient
95
+ - whether the request form needs supported operation-level UI metadata such as `select2` async search
96
+ - whether the response should render as a notification banner, an editable form session, or the generic response viewer
97
+ - the fields, sections, labels, and tokens a response-side editable form should expose
95
98
  - whether the output is:
96
99
  - a generic API contract
97
100
  - an exact widget-facing contract
@@ -118,26 +121,27 @@ If registry detail is not sufficient, and only after checking the SDK client mod
118
121
  - `mainsequence/client/command_center/app_component.py`
119
122
  - `mainsequence/client/command_center/data_models.py`
120
123
 
121
- If the input contract or output contract is unclear, stop before building the form.
124
+ If the request contract, response UI contract, or widget-facing output contract is unclear, stop before building the AppComponent contract.
122
125
 
123
126
  ## Required Decisions
124
127
 
125
128
  For every non-trivial AppComponent task, decide:
126
129
 
127
- 1. Is the default generated form sufficient?
128
- 2. If not, what requires a custom `EditableFormDefinition`?
129
- 3. What are the stable field tokens?
130
- 4. What field kinds should the frontend render?
131
- 5. Is the output generic, or does it need an exact widget-facing response contract?
132
- 6. If the AppComponent depends on a project API, does that API already exist as a FastAPI project resource with a FastAPI `ResourceRelease`?
130
+ 1. Is the default generated request form sufficient?
131
+ 2. If not, can the request-side need be handled by supported OpenAPI UI metadata such as `select2` async search?
132
+ 3. Should the response render as generic JSON/form output, a `NotificationDefinition`, or an `EditableFormDefinition` session?
133
+ 4. What are the stable field tokens for editable-form responses?
134
+ 5. What field kinds should the frontend render?
135
+ 6. Is the output generic, or does it need an exact widget-facing response contract?
136
+ 7. If the AppComponent depends on a project API, does that API already exist as a FastAPI project resource with a FastAPI `ResourceRelease`?
133
137
 
134
138
  ## Build Rules
135
139
 
136
- ### 1. Default generated form first
140
+ ### 1. Default generated request form first
137
141
 
138
- Do not jump to a custom form by default.
142
+ Do not jump to a response-side editable form by default.
139
143
 
140
- If the operation only exposes simple flat arguments with a straightforward shape, let Command Center resolve the form automatically.
144
+ If the operation only exposes simple flat arguments with a straightforward shape, let Command Center resolve the request form automatically from OpenAPI parameters and request body schema.
141
145
 
142
146
  Typical cases where default generation is enough:
143
147
 
@@ -176,9 +180,14 @@ This skill does not create resources or releases. If the FastAPI project resourc
176
180
 
177
181
  Only return to AppComponent contract work once the backing API deployment surface is real on the platform.
178
182
 
179
- ### 2. Use `EditableFormDefinition` only when the form needs to be specialized
183
+ ### 2. Use `EditableFormDefinition` only for response-side editable form sessions
180
184
 
181
- Use a custom form when the widget needs:
185
+ `EditableFormDefinition` is a response model. Command Center renders it after the operation returns successfully when the selected operation's primary success response advertises:
186
+
187
+ - `"x-ui-role": "editable-form"`
188
+ - `"x-ui-widget": "definition-v1"`
189
+
190
+ Use it when the response should become a stateful editable form session with:
182
191
 
183
192
  - grouped sections
184
193
  - domain-specific labels
@@ -186,7 +195,14 @@ Use a custom form when the widget needs:
186
195
  - more control over editable vs read-only behavior
187
196
  - stable custom tokens for bindings or draft state
188
197
 
189
- Do not use a custom form just to restate a trivial flat contract.
198
+ Do not use `EditableFormDefinition` to define the pre-submit request form. Request inputs are generated from OpenAPI path, query, header, and JSON body metadata. If the request side needs richer behavior, use supported operation-level UI metadata instead of returning a form definition.
199
+
200
+ The current supported request-side UI enhancement is:
201
+
202
+ - `"x-ui-widget": "select2"`
203
+ - `"x-ui-role": "async-select-search"`
204
+
205
+ This enhancement is resolved from the selected OpenAPI operation metadata and currently targets query-parameter search helpers on that operation.
190
206
 
191
207
  ### 3. Treat tokens as stable identities
192
208
 
@@ -212,7 +228,10 @@ Example:
212
228
 
213
229
  Keep the boundary clear:
214
230
 
215
- - `EditableFormDefinition` and related form objects describe what the widget should collect
231
+ - OpenAPI parameters and request body schemas describe what the widget should collect before execution
232
+ - operation-level `select2` metadata can specialize supported request-side generated fields
233
+ - `EditableFormDefinition` and related form objects describe a response-side editable form session
234
+ - `NotificationDefinition` describes response-side banner feedback
216
235
  - `mainsequence.client.command_center.data_models.TabularFrameResponse` is the SDK canonical model for `core.tabular_frame@v1`
217
236
  - other SDK widget data models describe specialized widget-facing API responses when those exist
218
237
 
@@ -265,24 +284,37 @@ Do not use AppComponent as a shortcut source node for generic workspace data jus
265
284
  operation itself is the intended form-driven action or workflow producing the canonical tabular
266
285
  result.
267
286
 
268
- ### 6.2 `x-ui-role` is what makes the contract render as richer UI
287
+ ### 6.2 `x-ui-role` is what makes supported contracts render as richer UI
269
288
 
270
- For AppComponent contracts, prefer SDK models whose OpenAPI schema carries the explicit UI role markers.
289
+ For AppComponent response contracts, prefer SDK models whose OpenAPI schema carries the explicit UI role markers.
271
290
 
272
291
  The AppComponent should always try to implement:
273
292
 
274
- - `"x-ui-role": "editable-form"` for input-side contracts
275
- - `"x-ui-role": "notification"` for response-side contracts
293
+ - `"x-ui-role": "editable-form"` with `"x-ui-widget": "definition-v1"` for response-side editable form sessions
294
+ - `"x-ui-role": "notification"` with `"x-ui-widget": "banner-v1"` for response-side banner feedback
295
+
296
+ For request-side generated form enhancements, the current supported operation-level contract is:
297
+
298
+ - `"x-ui-role": "async-select-search"` with `"x-ui-widget": "select2"`
276
299
 
277
300
  These markers are not cosmetic. They are what tell Command Center to treat the payload as a richer UI contract instead of generic JSON.
278
301
 
279
302
  That means:
280
303
 
281
- - use `EditableFormDefinition` and related input models when the AppComponent needs a specialized input form
304
+ - use OpenAPI parameters and request bodies for pre-submit inputs
305
+ - use operation-level `select2` metadata when a request field should render as an async search input
306
+ - use `EditableFormDefinition` and related models when the AppComponent response should render as a stateful editable form
282
307
  - use `NotificationDefinition` for response-side user feedback when the backend should return a banner-style notification
283
308
  - do not handcraft loose dictionaries for these cases when the SDK model already exists
284
309
  - keep input and response contracts separate instead of overloading one model to do both jobs
285
310
 
311
+ Current frontend resolution details matter:
312
+
313
+ - generated request forms come from OpenAPI path, query, header, and JSON body metadata
314
+ - request-side `select2` metadata is read from the selected OpenAPI operation
315
+ - response-side editable-form and notification metadata is read from the primary success response schema first, then from the operation metadata
316
+ - placing these response UI markers only on the OpenAPI media-type or response object is not sufficient in the current frontend
317
+
286
318
  ### 6.3 AppComponent bindings are dynamic, port-to-port, and response-shape aware
287
319
 
288
320
  Treat AppComponent bindings as normal canonical widget bindings, not as a separate AppComponent-only
@@ -369,8 +401,8 @@ When reviewing an AppComponent task, look for:
369
401
 
370
402
  - inferred or guessed `widget_id` values
371
403
  - AppComponent work that skipped `registered_widget_type list/detail`
372
- - a custom form that should have been auto-generated
373
- - a flat autogenerated form that should have been specialized
404
+ - a response-side editable form being used where the request form should simply be generated from OpenAPI
405
+ - a flat autogenerated request form that should have used supported operation-level UI metadata
374
406
  - unstable or poorly named field tokens
375
407
  - wrong `FormFieldKind` choices
376
408
  - generic API output being used where an exact widget-facing contract should have been returned
@@ -388,14 +420,16 @@ Do not claim success until you have checked:
388
420
  - `mainsequence cc registered_widget_type list --json`
389
421
  - `mainsequence cc registered_widget_type detail <WIDGET_ID> --json`
390
422
  - registry detail was used as the first source of truth
391
- - the choice between autogenerated form and custom form is intentional
392
- - custom forms use `EditableFormDefinition`
423
+ - the choice between autogenerated request form and supported request-side UI metadata is intentional
424
+ - response-side editable forms use `EditableFormDefinition`
425
+ - response-side notifications use `NotificationDefinition`
393
426
  - sections and fields are explicit where needed
394
427
  - field tokens are stable and meaningful
395
428
  - field kinds reflect business meaning
396
429
  - input and output contracts are not mixed together
397
- - input-side AppComponent contracts use `"x-ui-role": "editable-form"` when a specialized form is intended
398
- - response-side AppComponent contracts use `"x-ui-role": "notification"` when the API is returning user-facing banner feedback
430
+ - request-side AppComponent enhancements use operation-level `"x-ui-role": "async-select-search"` with `"x-ui-widget": "select2"` when async search is intended
431
+ - response-side AppComponent contracts use `"x-ui-role": "editable-form"` with `"x-ui-widget": "definition-v1"` when the API is returning a stateful editable form
432
+ - response-side AppComponent contracts use `"x-ui-role": "notification"` with `"x-ui-widget": "banner-v1"` when the API is returning user-facing banner feedback
399
433
  - widget-facing outputs use exact SDK response models when applicable
400
434
  - generic tabular consumers receive `core.tabular_frame@v1`
401
435
  - AppComponent operations producing full canonical tabular frames use `TabularFrameResponse`
@@ -411,7 +445,8 @@ Do not claim success until you have checked:
411
445
  - the task depends on guessed widget behavior without registry verification
412
446
  - registry detail is insufficient and the required contract cannot be resolved from Main Sequence docs/models in this repository
413
447
  - the task is really about workspace structure instead of AppComponent contracts
414
- - the form contract is unclear but a custom form is being forced anyway
448
+ - the request form contract is unclear but a response-side editable form is being forced anyway
449
+ - the response UI contract is unclear but `EditableFormDefinition` or `NotificationDefinition` is being forced anyway
415
450
  - the widget-facing output contract is unclear and no exact SDK model is available
416
451
  - the task is really a generic API design problem rather than an AppComponent problem
417
452
  - the AppComponent depends on a project API that does not yet exist as a FastAPI resource and FastAPI `ResourceRelease`
@@ -2375,6 +2375,23 @@ class DataNodeUpdate(TableUpdateNode, BaseObjectOrm):
2375
2375
 
2376
2376
  return depth_df
2377
2377
 
2378
+ def clear_dependencies(self, timeout=None) -> dict[str, Any] | None:
2379
+ url = self.get_object_url() + f"/{self._public_uid()}/clear-dependencies/"
2380
+ payload = {"json": {}}
2381
+ r = make_request(
2382
+ s=self.build_session(),
2383
+ loaders=self.LOADERS,
2384
+ r_type="POST",
2385
+ url=url,
2386
+ payload=payload,
2387
+ time_out=timeout,
2388
+ )
2389
+ if r.status_code not in (200, 204):
2390
+ raise_for_response(r, payload=payload)
2391
+ if not r.content:
2392
+ return None
2393
+ return r.json()
2394
+
2378
2395
  @classmethod
2379
2396
  def get_upstream_nodes(cls, storage_hash, data_source_uid, timeout=None):
2380
2397
  s = cls.build_session()
@@ -3010,6 +3027,56 @@ class TimeIndexMetaTable(MetaTable):
3010
3027
  descriptor[key] = cls._date_for_payload(descriptor[key])
3011
3028
  return normalized
3012
3029
 
3030
+ def _identity_dimensions_from_time_indexed_profile(self) -> list[str]:
3031
+ profile = self.time_indexed_profile
3032
+ if profile is None:
3033
+ raise ValueError(
3034
+ "Cannot validate dimension_range_map because TimeIndexMetaTable "
3035
+ "is missing time_indexed_profile."
3036
+ )
3037
+
3038
+ time_index_name = str(profile.time_index_name)
3039
+ index_names = [str(name) for name in profile.index_names]
3040
+ if not time_index_name or not index_names:
3041
+ raise ValueError(
3042
+ "Cannot validate dimension_range_map because TimeIndexMetaTable "
3043
+ "time_indexed_profile is missing time_index_name or index_names."
3044
+ )
3045
+ return [name for name in index_names if name != time_index_name]
3046
+
3047
+ def _validate_dimension_range_map_coordinates(
3048
+ self,
3049
+ dimension_range_map: list[dict[str, Any]] | None,
3050
+ ) -> None:
3051
+ if not dimension_range_map:
3052
+ return
3053
+
3054
+ expected_dimensions = self._identity_dimensions_from_time_indexed_profile()
3055
+ if not expected_dimensions:
3056
+ return
3057
+
3058
+ for position, descriptor in enumerate(dimension_range_map):
3059
+ coordinate = descriptor.get("coordinate") if isinstance(descriptor, Mapping) else None
3060
+ provided_dimensions = (
3061
+ [str(name) for name in coordinate.keys()]
3062
+ if isinstance(coordinate, Mapping)
3063
+ else []
3064
+ )
3065
+ provided_set = set(provided_dimensions)
3066
+ missing_dimensions = [
3067
+ dimension
3068
+ for dimension in expected_dimensions
3069
+ if dimension not in provided_set
3070
+ ]
3071
+ if missing_dimensions:
3072
+ raise ValueError(
3073
+ "dimension_range_map coordinate is incomplete for "
3074
+ "TimeIndexMetaTable read. "
3075
+ f"Entry {position} expected identity dimensions "
3076
+ f"{expected_dimensions!r}; provided {provided_dimensions!r}; "
3077
+ f"missing {missing_dimensions!r}."
3078
+ )
3079
+
3013
3080
  def _build_dimension_payload(
3014
3081
  self,
3015
3082
  *,
@@ -3023,6 +3090,7 @@ class TimeIndexMetaTable(MetaTable):
3023
3090
  if index_coordinates is not None:
3024
3091
  payload["index_coordinates"] = index_coordinates
3025
3092
  if dimension_range_map is not None:
3093
+ self._validate_dimension_range_map_coordinates(dimension_range_map)
3026
3094
  payload["dimension_range_map"] = self._normalize_dimension_range_map(
3027
3095
  dimension_range_map
3028
3096
  )
@@ -3309,7 +3377,7 @@ class TimeIndexMetaTable(MetaTable):
3309
3377
  )
3310
3378
  if r.status_code != 200:
3311
3379
  logger.warning(f"Error in request: {r.text}")
3312
- return [], None
3380
+ raise_for_response(r, payload=payload)
3313
3381
 
3314
3382
  response_data = r.json()
3315
3383
  # Accumulate results
@@ -807,12 +807,29 @@ class DataNode(DataAccessMixin, ABC):
807
807
  local_configuration=self.local_initial_configuration,
808
808
  )
809
809
 
810
- def set_relation_tree(self):
810
+ def set_relation_tree(
811
+ self,
812
+ *,
813
+ force_rebuild: bool = False,
814
+ _visited_update_uids: set[str] | None = None,
815
+ ):
811
816
  """Sets the node relationships in the backend by calling the dependencies() method."""
812
817
 
813
818
  if self.local_persist_manager.data_node_update is None:
814
819
  self.verify_and_build_remote_objects() #
815
- if self.local_persist_manager.is_local_relation_tree_set():
820
+ data_node_update_uid = str(getattr(self.local_persist_manager.data_node_update, "uid", ""))
821
+ if _visited_update_uids is None:
822
+ _visited_update_uids = set()
823
+ if data_node_update_uid:
824
+ if data_node_update_uid in _visited_update_uids:
825
+ return
826
+ _visited_update_uids.add(data_node_update_uid)
827
+
828
+ if force_rebuild:
829
+ self.local_persist_manager.clear_dependencies()
830
+ self.depth_df = pd.DataFrame()
831
+ self.dependencies_df = None
832
+ elif self.local_persist_manager.is_local_relation_tree_set():
816
833
  return
817
834
  declared_dependencies = self.dependencies() or {}
818
835
 
@@ -827,7 +844,11 @@ class DataNode(DataAccessMixin, ABC):
827
844
  self.local_persist_manager.depends_on_connect(dependency_ts, is_api=is_api)
828
845
 
829
846
  # Recursively set the relation tree for the dependency
830
- dependency_ts.set_relation_tree()
847
+ if not is_api:
848
+ dependency_ts.set_relation_tree(
849
+ force_rebuild=force_rebuild,
850
+ _visited_update_uids=_visited_update_uids,
851
+ )
831
852
 
832
853
  self.local_persist_manager.set_ogm_dependencies_linked()
833
854
 
@@ -996,7 +1017,7 @@ class DataNode(DataAccessMixin, ABC):
996
1017
  self.logger.warning(f"{self} produced no new data in this update round.")
997
1018
  return temp_df
998
1019
 
999
- if update_statistics_max_time_index is None and not SessionDataSource.is_local_db:
1020
+ if update_statistics_max_time_index is not None and not SessionDataSource.is_local_db:
1000
1021
  temp_df = self.update_statistics.filter_df_by_latest_value(temp_df)
1001
1022
 
1002
1023
  if temp_df.empty: