loom-kernel 8.0.1__tar.gz → 9.0.0__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.
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/CHANGELOG.md +382 -23
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/PKG-INFO +5 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/README.md +4 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +6 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +7 -12
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +11 -6
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +3 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/errors.py +48 -10
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_lifecycle.py +5 -6
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/bootstrap.py +15 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/cli/check.py +1 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/backend/sqlalchemy.py +24 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/decorators.py +4 -5
- loom_kernel-9.0.0/src/loom/core/cache/keys.py +186 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/repository.py +263 -148
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/result_codec.py +5 -29
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/checks.py +14 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/keys.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/overrides.py +15 -7
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/executor.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/environment.py +21 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/__init__.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/convert.py +31 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/field.py +9 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/introspection.py +50 -8
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/timestamped.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/types.py +1 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/types_postgres.py +1 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/plugins/entrypoints.py +5 -13
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/__init__.py +21 -4
- loom_kernel-9.0.0/src/loom/core/repository/abc/checks.py +60 -0
- loom_kernel-9.0.0/src/loom/core/repository/abc/cursor.py +682 -0
- loom_kernel-9.0.0/src/loom/core/repository/abc/session_scope.py +60 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/repository.py +7 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/backend.py +11 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/ids.py +6 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/registry.py +19 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/repository.py +57 -27
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/backend.py +10 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/mixins.py +37 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +55 -14
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +34 -12
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/registry.py +25 -8
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/repository.py +17 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/session_manager.py +8 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/values.py +47 -31
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/__init__.py +1 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/compute.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/invoker.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/rule.py +6 -11
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/__init__.py +4 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/_policy.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_write_policy.py +13 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_reader.py +0 -6
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_schema.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_writer.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_schema.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_writer.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/__init__.py +0 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_cleaners.py +3 -7
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_store.py +2 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_filter.py +2 -30
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/_with_agent.py +5 -16
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -4
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_specs.py +0 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/__init__.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_builder.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_spec.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_into.py +5 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_table.py +1 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_clickhouse.py +2 -3
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/__init__.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/core.py +1 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/schema/_schema.py +11 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_discovery.py +4 -2
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/compiler.py +161 -50
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/app.py +15 -49
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/auto.py +2 -1
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/openapi.py +8 -18
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/router_runtime.py +10 -6
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/model.py +8 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_adapter.py +35 -9
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_runtime_io.py +3 -7
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/runner.py +6 -5
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_errors.py +6 -17
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_plan.py +18 -15
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/phases/build_plan.py +2 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/phases/validate.py +8 -29
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_config.py +20 -28
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/common.py +206 -159
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/config.py +21 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/repository_harness.py +7 -1
- loom_kernel-8.0.1/src/loom/core/cache/keys.py +0 -96
- loom_kernel-8.0.1/src/loom/core/repository/abc/cursor.py +0 -157
- loom_kernel-8.0.1/src/loom/core/repository/abc/session_scope.py +0 -37
- loom_kernel-8.0.1/src/loom/etl/declarative/target/_schema_mode.py +0 -5
- loom_kernel-8.0.1/src/loom/etl/runner/errors.py +0 -7
- loom_kernel-8.0.1/src/loom/etl/runner/filtering.py +0 -41
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/.gitignore +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/LICENSE +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/pyproject.toml +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_concurrency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_filters.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_startup.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_transport.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/_usecase.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/_binding.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/_handlers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/_rpc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/card.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/a2a/server.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/_plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_capabilities.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_output.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_state.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/declarative/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/declarative/_envelope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/declarative/_schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/declarative/_v1.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/describe.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_batch.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_columns.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_frames.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_ledger.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/etl/_validation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/fastapi/endpoints.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/fastapi/response.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/fastapi/streaming.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/inference.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/pricing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/remote_auth.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_bounded.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_chain.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_conversation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_grants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_handle.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_health.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_hooks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_limits.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/runtime/_mcp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/validate/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/ai/validate/__main__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/auto.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/celery/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/cli/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/cli/app.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/cli/schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/async_bridge.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/_decide.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/_grants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/_roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/_scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/elevation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/authz/product.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/backend/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/backend/core_model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/backend/protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/backend/scoped_ddl.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/bootstrap/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/bootstrap/kernel.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/_batching.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/_single_flight.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/abc/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/abc/backend.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/abc/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/abc/dependency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/calls.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/codec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/dependency.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/gateway.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/memory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/serializer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/cache/wiring.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/command/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/command/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/command/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/command/field.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/command/introspection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/_boto3.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/_includes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/_resolver_utils.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/binder.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/configurable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/loader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/observability.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/secrets.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/config/ssm.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/contracts/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/contracts/manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/di/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/di/container.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/di/scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/_utils.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/interfaces.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/discovery/modules.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/compilable.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/events.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/metrics.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/engine/post_commit.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/errors/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/errors/codes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/errors/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/expr/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/expr/eval.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/expr/nodes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/expr/refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/identity/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/identity/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/identity/identity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/identity/issuer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/identity/wire.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/introspection/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/introspection/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/introspection/describe.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/callback.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/handle.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/job.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/job/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/locator.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/checks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/logger/structlogger.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/_json_schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/_loom_type.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/enums.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/partition.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/privilege.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/projection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/relation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/scoped.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/model/struct.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/observer/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/observer/noop.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/observer/otel.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/observer/structlog.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/otel_ids.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/span.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/observability/topology.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/persistence/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/persistence/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/persistence/none.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/persistence/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/plugins/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/plugins/optional.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/projection/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/projection/loaders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/projection/runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/query.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/repo_for.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/abc/repository.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/backend.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/values.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/mutation.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/registration.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/response/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/response/base.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/routing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/routing/ref.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/routing/resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/schema/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/schema/schema_mode.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/schema_names.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/abc/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/abc/contracts.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/abc/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/caller_bound.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/_client.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/roles.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/sql/service.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/symbols.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/tracing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/tracing/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/transaction.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/transport/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/transport/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/uow/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/uow/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/uow/context.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/_predicates.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/agent_markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/factory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/field_ref.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/keys.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/mcp_markers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/outcome.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/core/use_case/use_case.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/_uri.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_format_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_common.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_log.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_merge.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_path_template.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_frame.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_historify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_historify.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_reader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/provider.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_paths.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_scope.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_binding.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_plan.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/_format.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/_read_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/_utils.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/_write_options.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_client.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_file.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_temp.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/executor/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/executor/_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/executor/_dispatcher.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/executor/_executor.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_serialization.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/targets/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/io/targets/_clickhouse.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/_observer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/_records.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_builder.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_ops.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_runner.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_generics.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_process.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_sql.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step_client.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/_agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/_providers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/_wiring.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runner/config_loader.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runtime/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runtime/_config_values.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/runtime/contracts.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/schema/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/schema/_contract.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/storage/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/storage/_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/storage/_file_locator.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/storage/_locator.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/storage/routing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/_result.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/_runners.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/_scenario.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/_stubs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/etl/testing/spark.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_async.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_ctx.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_flow_yaml.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_meta.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_placeholders.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/_summary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/deploy/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_schedule.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_assemble.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_backfill.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_body.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_common.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_factory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_hooks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_maintenance.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_params.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_run_name.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_runtime.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_signature.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/flow/_stages.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/manifest/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_model.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_s3.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_store.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_factory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_format.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_port.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_slack.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/notify/_sns.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/observer/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/observer/_flow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/observer/_manifest.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prefect/observer/_task_run.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/_instruments.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/kafka.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/lifecycle.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/prometheus/middleware.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/py.typed +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/_body.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/auth/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/auth/abc.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/auth/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/auth/jwt.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/auth/middleware.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/autocrud.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/checks.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/constants.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/cors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/health.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/response.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/fastapi/sql.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/middleware.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/rest/rest_adapter.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_operators.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/_shared.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_bindings.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/_exceptions.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/_message.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/_tracing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/core/_typing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/graph/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/graph/_flow.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_codec.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_errors.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_message.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_record.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_wire.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/mongo/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_config.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_event.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_normalize.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_boundary.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_branches.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_decompose.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_fork.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_helpers.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_mongo.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_protocols.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_router.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_shape.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_sink.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_step.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_with.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/nodes/refs.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/streaming/testing.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/__init__.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/agents.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/golden.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/http_harness.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/in_memory.py +0 -0
- {loom_kernel-8.0.1 → loom_kernel-9.0.0}/src/loom/testing/runner.py +0 -0
|
@@ -412,7 +412,7 @@
|
|
|
412
412
|
selection can be checked without running it. A bare string as `include`
|
|
413
413
|
raises `TypeError`. The runner now filters through it. `InvalidStageError`
|
|
414
414
|
is exported from `loom.etl.compiler` as well; it is the same class as
|
|
415
|
-
`loom.etl.
|
|
415
|
+
`loom.etl.InvalidStageError`.
|
|
416
416
|
- **etl:** `iter_processes`, `iter_steps_in_process` and `iter_all_steps` are
|
|
417
417
|
exported from `loom.etl.compiler`. They flatten a compiled plan in
|
|
418
418
|
execution order, parallel groups in declaration order, so code that walks
|
|
@@ -459,6 +459,68 @@
|
|
|
459
459
|
|
|
460
460
|
### core
|
|
461
461
|
|
|
462
|
+
- **core:** `RuleViolation` and `RuleViolations` are no longer exported by
|
|
463
|
+
`loom.core.use_case` or `loom.core.use_case.rule`. Import them from
|
|
464
|
+
`loom.core.errors`, their only public home.
|
|
465
|
+
- **core:** wrapping a repository in `CachedRepository` raises `RuntimeError`
|
|
466
|
+
when one of its `@cache_query` reads has a missing return annotation, one
|
|
467
|
+
the defining module cannot resolve, or one outside the supported grammar,
|
|
468
|
+
naming the repository and the method; a `@cached` repository therefore fails
|
|
469
|
+
when it is built. Before, wrapping emitted a `DeprecationWarning` and logged
|
|
470
|
+
`CacheQueryReturnTypeUnusable`, and the cached call returned the decoded
|
|
471
|
+
payload instead of the declared type. Annotate the read's return type with a
|
|
472
|
+
struct, a scalar, or a `list`, `tuple` or optional of those. A
|
|
473
|
+
`@cache_query` coroutine that is not defined on the repository class, such
|
|
474
|
+
as one set on the instance, raises `RuntimeError` when it is looked up on
|
|
475
|
+
the wrapper, since no codec was built for it; define it as a method of the
|
|
476
|
+
class.
|
|
477
|
+
- **core:** a field annotated `X | UnsetType` infers `X`'s column type.
|
|
478
|
+
`UNSET` means "not provided", not another type, so `str | UnsetType` now
|
|
479
|
+
compiles to `String` and `int | UnsetType` to `Integer` instead of `JSON`,
|
|
480
|
+
and `Annotated[str, String(20)] | UnsetType` reads its declared type. Such
|
|
481
|
+
a column is scalar: a REST route may declare it filterable, `like` and
|
|
482
|
+
`ilike` included for text, and sortable by offset; a cursor sort on it is
|
|
483
|
+
still refused, since a cursor key must be a bare type. Nullability is
|
|
484
|
+
unchanged: `str | None | UnsetType` admits `None` and is nullable,
|
|
485
|
+
`UnsetType` alone keeps the column `NOT NULL`. An undeclared
|
|
486
|
+
`Decimal | UnsetType`, plain `Enum | UnsetType` or `Literal[...] | UnsetType`
|
|
487
|
+
now needs a declared column type, as it does without `UnsetType`. On Mongo,
|
|
488
|
+
a `str | UnsetType` or `UUID | UnsetType` primary key is now accepted, and
|
|
489
|
+
a range filter or sort on a `Decimal | UnsetType` field is refused, as on a
|
|
490
|
+
`Decimal` field. Alembic autogenerate will show the type change from `JSON`
|
|
491
|
+
for existing tables with such columns.
|
|
492
|
+
- **core:** a column's nullability follows its field's annotation. A field
|
|
493
|
+
whose annotation admits `None` (`x: int | None = None`, also inside
|
|
494
|
+
`Annotated`) compiles to a nullable column; any other field compiles to
|
|
495
|
+
`NOT NULL`, and a primary key column is `NOT NULL` whatever its annotation.
|
|
496
|
+
Before, every column was `NOT NULL` unless declared otherwise, so the model
|
|
497
|
+
accepted `None` and the database refused it on insert. `nullable=` on
|
|
498
|
+
`ColumnField`, `ScopedField` or `Field` now defaults to `None` (follow the
|
|
499
|
+
annotation) and a declared `True` or `False` still wins. Alembic
|
|
500
|
+
autogenerate will propose `nullable` changes for existing tables whose
|
|
501
|
+
Optional fields were created `NOT NULL`; to keep such a column `NOT NULL`,
|
|
502
|
+
declare `nullable=False`. ETL schema contracts keep their own rule (a
|
|
503
|
+
column is nullable unless declared otherwise), which this change does not
|
|
504
|
+
touch.
|
|
505
|
+
- **core:** a `uuid.UUID` field without a declared column type is now a
|
|
506
|
+
`Uuid` column (`loom.core.model.Uuid`, SQLAlchemy `Uuid`) instead of
|
|
507
|
+
`JSON`: `UUID` on Postgres, `CHAR(32)` holding the hex form on dialects
|
|
508
|
+
without a native UUID type, such as SQLite. Such a field is now a scalar
|
|
509
|
+
column, so REST `filterable`, `sortable` and `ALL` accept it on every
|
|
510
|
+
backend, `mongo` included; on SQLite a cursor walk sorted by it pages in
|
|
511
|
+
UUID order and an equality filter on it matches. Streaming `IntoTable` with the
|
|
512
|
+
SQLAlchemy backend binds a `UUID` field the same way instead of failing to
|
|
513
|
+
serialise it as JSON. Migration: an existing table with such a column needs
|
|
514
|
+
a revision changing its type; Alembic autogenerate reports it as a type
|
|
515
|
+
change from `JSON` to `Uuid`. Postgres does not cast `json` to `uuid`, so
|
|
516
|
+
the revision needs `postgresql_using="(<column> #>> '{}')::uuid"`. On a
|
|
517
|
+
dialect without a native UUID type the old rows hold JSON text (the quoted
|
|
518
|
+
UUID with dashes), which the `Uuid` column cannot read, so after the type
|
|
519
|
+
change the revision rewrites each value to its 32-character hex. On
|
|
520
|
+
SQLite: `op.batch_alter_table` for the type change, then
|
|
521
|
+
`UPDATE <table> SET <column> = replace(json_extract(<column>, '$'), '-', '')`.
|
|
522
|
+
Rewriting before the type change loses values on SQLite: a hex form made
|
|
523
|
+
only of digits is stored as a number in the `JSON` column.
|
|
462
524
|
- **core:** a `Decimal` field, plain or optional, declares its column type: a
|
|
463
525
|
SQLAlchemy model with an undeclared one is refused when it is compiled,
|
|
464
526
|
naming the field. loom inferred `NUMERIC(10, 2)`, and Postgres silently
|
|
@@ -560,6 +622,81 @@
|
|
|
560
622
|
or `RuleViolation` it returns no longer fails the rule. Migrate
|
|
561
623
|
`Rule.check(F(Order).total, via=lambda v: v <= 0, message="total must be > 0")`
|
|
562
624
|
to `Rule.check(F(Order).total, via=lambda v: "total must be > 0" if v <= 0 else None)`.
|
|
625
|
+
- **core:** cursor signing keys are required (ADR 0004). An application whose
|
|
626
|
+
persistence backend serves repositories (`sqlalchemy`, `mongo`), and a
|
|
627
|
+
Celery worker that registers repositories, read `persistence.cursors` at
|
|
628
|
+
startup and fail with a `ConfigError` without a key:
|
|
629
|
+
|
|
630
|
+
```yaml
|
|
631
|
+
persistence:
|
|
632
|
+
cursors:
|
|
633
|
+
current_key_id: "2026-10"
|
|
634
|
+
keys:
|
|
635
|
+
"2026-10": {env: CURSOR_KEY_2026_10} # or {path: /run/secrets/...}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
Keys are read from a file or an environment variable, never written in the
|
|
639
|
+
configuration, as standard base64 decoding to at least 32 random bytes
|
|
640
|
+
(`openssl rand -base64 32`); a passphrase is refused. Older key ids stay in
|
|
641
|
+
`keys` to verify the tokens they signed during a rotation.
|
|
642
|
+
The default is `signed` in every environment; `signing: ephemeral` (a
|
|
643
|
+
random per-process key, for `development.yaml`) and `signing: unsigned`
|
|
644
|
+
(for `test.yaml`) are explicit opt-outs, and both log a WARNING at
|
|
645
|
+
startup. In production and staging the deploy check `loom.cursors.E001`
|
|
646
|
+
fails startup, and `loom check --deploy` fails, when a `database` or
|
|
647
|
+
`persistence.mongo` section is set and `signing` is not `signed` or
|
|
648
|
+
`current_key_id` names no entry of `keys`. No `config.overridable` entry
|
|
649
|
+
may open a key under `persistence.cursors`. A key's `env` source must not
|
|
650
|
+
name a `LOOM_*` variable. Tokens issued before this release are refused:
|
|
651
|
+
clients restart from the first page.
|
|
652
|
+
- **core:** a cursor page orders only by non-null columns of a type a token
|
|
653
|
+
carries; a dotted path, a JSON, `bytes` or optional column answers
|
|
654
|
+
`400 unsupported_query` before the query runs (`require_cursor_sort`), and
|
|
655
|
+
a page whose last row holds a non-finite number or a value the token
|
|
656
|
+
cannot carry answers 400 instead of 500. An empty cursor is an invalid
|
|
657
|
+
token on SQLAlchemy as on Mongo. Tokens bind the model as
|
|
658
|
+
`module.qualname`; `UnsupportedQuery` and the client's 400 name it by its
|
|
659
|
+
qualified name alone. `CursorCodec.encode`/`decode`, `require_cursor_sort`
|
|
660
|
+
and `QuerySpecCompiler(model=...)` take the model class (or a name). Mongo
|
|
661
|
+
issues the next token in the model's types, so a page sorted by a date or
|
|
662
|
+
UUID column, or keyed by a UUID, reaches the next page.
|
|
663
|
+
- **core:** one `CursorCodec` per process: the registration modules register
|
|
664
|
+
it with `register_cursor_codec`, which raises `ConfigError` when a
|
|
665
|
+
different codec is already registered, and, in a deployed environment,
|
|
666
|
+
for an `ephemeral` or `unsigned` codec unless `CursorCodec.from_context`
|
|
667
|
+
built it from a configuration silencing `loom.cursors.E001`. Without a
|
|
668
|
+
registered `Environment` the process environment decides (`LOOM_ENV`, else
|
|
669
|
+
production).
|
|
670
|
+
- **core:** `loom.core.checks.silenced_checks(config)` returns the ids
|
|
671
|
+
`checks.silenced` lists, as the deploy-check runner reads them.
|
|
672
|
+
- **core:** the unsigned module functions `encode_cursor` and
|
|
673
|
+
`decode_cursor` are gone. `CursorCodec` (with `CursorConfig` and
|
|
674
|
+
`CursorKeySource`, exported from `loom.core.repository.abc`) issues and
|
|
675
|
+
verifies tokens: `encode(cursor, *, model, query, scope)` and
|
|
676
|
+
`decode(token, *, backend, model, query, scope, columns, primary_key)`,
|
|
677
|
+
where `scope` is required and `""` binds a token to no tenant, `columns`
|
|
678
|
+
maps each column name to its annotation and `primary_key` names the key
|
|
679
|
+
columns in order. A sort key or primary-key value whose type is not its
|
|
680
|
+
column's is refused (`400 unsupported_query`), as is a sort field missing
|
|
681
|
+
from `columns`. The backends
|
|
682
|
+
register the codec they build in DI, so a service paginating by hand
|
|
683
|
+
resolves it with `container.resolve(CursorCodec)`. A decoded datetime key
|
|
684
|
+
is always aware. A `time` sort key is carried too, with the offset it was
|
|
685
|
+
issued with; before, a page sorted by a column holding `time` values
|
|
686
|
+
raised `TypeError` when it issued the next cursor.
|
|
687
|
+
- **core:** `RepositorySQLAlchemy`, `RepositoryMongo`, `QuerySpecCompiler`
|
|
688
|
+
(with a required `scope` and `columns` too), `SQLAlchemyDefaultRepositoryBuilder`,
|
|
689
|
+
`MongoDefaultRepositoryBuilder`, `build_sqlalchemy_repository_registration_module`,
|
|
690
|
+
`build_mongo_repository_registration_module` and
|
|
691
|
+
`loom.testing.build_repository_harness` take a required keyword-only
|
|
692
|
+
`cursor_codec`. A custom repository `builder` passes
|
|
693
|
+
`context.container.resolve(CursorCodec)`. `extract_next_cursor` returns the
|
|
694
|
+
next `Cursor` position instead of a token, and `SessionManager` gains
|
|
695
|
+
`current_settings()`. SQLAlchemy repositories bind cursors to the caller's
|
|
696
|
+
`loom.scope.*` session values. `loom.core.environment` gains
|
|
697
|
+
`configured_variable(name)`, which reads a variable a configuration names
|
|
698
|
+
and refuses a `LOOM_*` name.
|
|
699
|
+
|
|
563
700
|
- **core:** the `LoomType` protocol gains `from_query(params)`, which
|
|
564
701
|
validates query-string values strictly. A number takes the JSON number
|
|
565
702
|
grammar and must be finite, an integer its integer subset within
|
|
@@ -577,8 +714,7 @@
|
|
|
577
714
|
takes the tuple as its first argument and raises `TypeError` for anything
|
|
578
715
|
else. A cursor token issued for such a model before this release is refused with
|
|
579
716
|
`UnsupportedQuery`, `400 unsupported_query`; clients restart from the first
|
|
580
|
-
page. `
|
|
581
|
-
`get_id_attributes` returns every key column name.
|
|
717
|
+
page. `get_id_attributes` returns every key column name.
|
|
582
718
|
|
|
583
719
|
- **core:** `compile_all` raises `ValueError` for a model with a composite
|
|
584
720
|
primary key that declares a relation or a projection whose loader runs
|
|
@@ -673,6 +809,8 @@
|
|
|
673
809
|
present convert those rows deliberately (for example to UTC with
|
|
674
810
|
`(c::timetz AT TIME ZONE 'UTC')::time`) before changing the type. MongoDB is
|
|
675
811
|
unaffected: it stores `date` and `time` values as ISO 8601 strings.
|
|
812
|
+
- **core:** `to_column_value` is imported from `loom.core.model.convert`; it is
|
|
813
|
+
no longer exported by `loom.core.repository.sqlalchemy.values`.
|
|
676
814
|
|
|
677
815
|
### ai
|
|
678
816
|
|
|
@@ -681,9 +819,15 @@
|
|
|
681
819
|
example `spec_malformed`, `engine_not_found` and `mcp_server_unreachable`.
|
|
682
820
|
Build an issue with `AgentErrorCode.X.issue(...)` and keyword arguments,
|
|
683
821
|
such as `AgentErrorCode.ENGINE_NOT_FOUND.issue(component="openai-agents",
|
|
684
|
-
available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too
|
|
685
|
-
|
|
686
|
-
|
|
822
|
+
available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too.
|
|
823
|
+
Messages keep their text; a list that is empty renders `none`.
|
|
824
|
+
- **ai:** `AgentCompilationError` takes `AgentCompilationIssue` values only;
|
|
825
|
+
bare strings and the `AgentErrorCode.UNSPECIFIED` code they became are
|
|
826
|
+
removed. Build an issue from an `AgentErrorCode` member with `.issue()`.
|
|
827
|
+
The five pydantic-ai engine failures that raised bare strings now carry
|
|
828
|
+
their own codes, with the same messages: `TOOL_NAME_COLLISION`,
|
|
829
|
+
`TOOL_NAME_TOO_LONG`, `USECASE_NOT_COMPILED`, `CAPABILITY_KIND_NO_BUILDER`
|
|
830
|
+
and `MCP_CONNECTION_NOT_OPENED`.
|
|
687
831
|
- **ai:** `AgentCompilationIssue` is a type alias of
|
|
688
832
|
`CompileIssue[AgentErrorCode]` from `loom.core.errors.codes`, not a class.
|
|
689
833
|
It has the same fields, but `isinstance` against it raises `TypeError`
|
|
@@ -762,6 +906,9 @@
|
|
|
762
906
|
declares both a pydantic `type_ref` output and `output_check` serialises
|
|
763
907
|
an accepted answer twice per attempt — once for the check's own builtins
|
|
764
908
|
projection, once for the wire — accepted rather than optimised away.
|
|
909
|
+
- **ai:** a provider's `credentials_ref` is read through
|
|
910
|
+
`loom.core.environment.configured_variable` and may not name a `LOOM_*`
|
|
911
|
+
variable.
|
|
765
912
|
|
|
766
913
|
### rest
|
|
767
914
|
|
|
@@ -824,6 +971,33 @@
|
|
|
824
971
|
`msgspec.ValidationError`. The root `title` is dropped on pydantic
|
|
825
972
|
OpenAPI schemas for request bodies and responses alike, matching the
|
|
826
973
|
untitled document a Struct always produced.
|
|
974
|
+
- **rest:** a `sortable` column must be a field of the items the route
|
|
975
|
+
answers with (`PageResult[T]`, `CursorResult[T]` or `list[T]`); a column
|
|
976
|
+
the response does not show, or a result type that does not say, fails
|
|
977
|
+
compilation naming the route and the field, since ordering by it reveals
|
|
978
|
+
its values. `sortable=ALL` opens every scalar column, hidden ones included,
|
|
979
|
+
and its startup warning says so. `filterable` follows the same rule, with
|
|
980
|
+
`filterable=ALL` as its escape hatch. "Shown" is decided by field name; a
|
|
981
|
+
pydantic field declared `exclude=True` is not shown.
|
|
982
|
+
- **rest:** breaking: a `QuerySpec` route that can serve cursor pages (cursor
|
|
983
|
+
mode, or the default `allow_pagination_override=True`) must answer with
|
|
984
|
+
items that show its primary key, which every cursor token carries. A route
|
|
985
|
+
whose response hides the key, or whose result type is untyped (`str`,
|
|
986
|
+
`dict[str, Any]`, ...), now fails compilation naming the route and the key.
|
|
987
|
+
`sortable=ALL` opens it with a warning; a route that must hide its keys
|
|
988
|
+
serves offset pages only (`pagination_mode` offset and
|
|
989
|
+
`allow_pagination_override=False`). On such a route the key must also be of
|
|
990
|
+
a type a token carries, in a scalar column: a key declared in a JSON or
|
|
991
|
+
array column, which a SQL keyset cannot order, fails compilation instead
|
|
992
|
+
of on the first cursor request. A bare `UUID` key, a scalar `Uuid` column,
|
|
993
|
+
compiles and pages on SQLAlchemy and Mongo alike.
|
|
994
|
+
- **rest:** `create_fastapi_app(interfaces=...)` is removed and `routes` is
|
|
995
|
+
required; use `create_fastapi_app(result, RouteSources(python=[...]))`.
|
|
996
|
+
- **rest:** the `QUERY_PARAM_PAGE`, `QUERY_PARAM_LIMIT`,
|
|
997
|
+
`QUERY_PARAM_PAGINATION`, `QUERY_PARAM_AFTER`, `QUERY_PARAM_CURSOR`,
|
|
998
|
+
`QUERY_PARAM_SORT`, `QUERY_PARAM_DIRECTION` and `QUERY_PARAM_PROFILE`
|
|
999
|
+
re-exports of `loom.rest.fastapi.openapi` are removed; use the matching
|
|
1000
|
+
`loom.rest.constants.QueryParam` member (`QueryParam.PAGE`, ...).
|
|
827
1001
|
|
|
828
1002
|
### prefect
|
|
829
1003
|
|
|
@@ -914,11 +1088,8 @@
|
|
|
914
1088
|
- **etl:** a `WithAgent` compiled by a runner whose config has no `ai:`
|
|
915
1089
|
section fails with the new code `AGENT_RUNNER_NOT_CONFIGURED` instead of
|
|
916
1090
|
`AGENT_NOT_FOUND`, which now means only that no artifact declares the name.
|
|
917
|
-
- **etl:**
|
|
918
|
-
`
|
|
919
|
-
`_map_process_nodes`) are deprecated and removed in loom 3.0; each emits a
|
|
920
|
-
`DeprecationWarning` naming its replacement, `loom.etl.compiler.filter_plan`
|
|
921
|
-
or, for `_collect_all_names`, `iter_processes` and `iter_all_steps`.
|
|
1091
|
+
- **etl:** `loom.etl.runner.filtering` is removed; use
|
|
1092
|
+
`loom.etl.compiler.filter_plan`.
|
|
922
1093
|
- **etl:** the Polars writer refuses, under `SchemaMode.STRICT` and
|
|
923
1094
|
`EVOLVE`, a frame column that is a `Struct` or `List` where the Delta table
|
|
924
1095
|
has `String`, or `String` where the table has a `Struct` or `List`, at any
|
|
@@ -937,8 +1108,7 @@
|
|
|
937
1108
|
`Unknown step or process names: [...]` instead of `No steps or processes
|
|
938
1109
|
match include=[...]`, the constructor's parameter is `unknown`, and the
|
|
939
1110
|
names are kept on the new `unknown` attribute. Positional construction is
|
|
940
|
-
unchanged
|
|
941
|
-
`DeprecationWarning` and is removed in loom 3.0. The error survives pickle
|
|
1111
|
+
unchanged. The error survives pickle
|
|
942
1112
|
with its `unknown` names, so it crosses process boundaries intact.
|
|
943
1113
|
- **etl:** `ThreadDispatcher` runs each task in a copy of the caller's
|
|
944
1114
|
context, as `asyncio.to_thread` does, so a step of a parallel group sees
|
|
@@ -949,16 +1119,75 @@
|
|
|
949
1119
|
caller's context among the requirements on an implementation.
|
|
950
1120
|
- **etl:** `WithAgent(max_usd=...)` keeps the budget as a `Decimal`. An
|
|
951
1121
|
`int`, or another `numbers.Integral` such as `numpy.int64`, is converted
|
|
952
|
-
exactly. A `
|
|
953
|
-
`
|
|
954
|
-
|
|
955
|
-
`
|
|
956
|
-
|
|
957
|
-
`
|
|
958
|
-
|
|
1122
|
+
exactly. A `bool`, accepted before, and any other type, such as `str`,
|
|
1123
|
+
raise `TypeError`. `NaN`, `sNaN` and `Infinity` raise `ValueError`, like
|
|
1124
|
+
zero and a negative amount; a `Decimal` `NaN` or `sNaN` used to raise
|
|
1125
|
+
`decimal.InvalidOperation`, and a `Decimal` `Infinity` was accepted.
|
|
1126
|
+
- **etl:** `InvalidStageError(include=...)` is removed; use
|
|
1127
|
+
`InvalidStageError(unknown=...)` or pass the names positionally.
|
|
1128
|
+
- **etl:** `WithAgent(max_usd=<float>)` is removed and raises `TypeError`;
|
|
1129
|
+
pass a `Decimal`, such as `Decimal("2.50")`, or an `int`.
|
|
1130
|
+
- **etl:** `loom.etl.CheckpointCleaner` and
|
|
1131
|
+
`loom.etl.checkpoint.CheckpointCleaner` are removed; use
|
|
1132
|
+
`FsspecTempCleaner`, now exported from `loom.etl` as well.
|
|
1133
|
+
- **etl:** the module `loom.etl.declarative.target._schema_mode` is removed;
|
|
1134
|
+
import `SchemaMode` from `loom.core.schema` (or `loom.etl`).
|
|
1135
|
+
- **etl:** `FromClickHouse.select(columns)` is removed; use
|
|
1136
|
+
`FromClickHouse.columns(*columns)`.
|
|
1137
|
+
- **etl:** `ClickHouseSourceSpec.table` is removed; use
|
|
1138
|
+
`ClickHouseSourceSpec.table_ref.ref`.
|
|
1139
|
+
- **etl:** `loom.etl.backends.polars._reader._apply_source_schema` is
|
|
1140
|
+
removed. It was a test helper and has no public replacement.
|
|
1141
|
+
- **etl:** the module `loom.etl.runner.errors` is removed, and neither
|
|
1142
|
+
`loom.etl.runner` nor `loom.etl.runner.core` exports `InvalidStageError`;
|
|
1143
|
+
import it from `loom.etl.compiler` (or `loom.etl`).
|
|
1144
|
+
- **etl:** `loom.etl.io.sources._clickhouse` no longer re-exports
|
|
1145
|
+
`FromClickHouse` and `ClickHouseSourceSpec`; import them from
|
|
1146
|
+
`loom.etl.declarative.source` (`FromClickHouse` also from `loom.etl`).
|
|
959
1147
|
|
|
960
1148
|
### streaming
|
|
961
1149
|
|
|
1150
|
+
- **streaming:** `ConsumerSettings.delivery` is required. A Kafka consumer
|
|
1151
|
+
config without `delivery` fails to decode, so compiling a flow that reads
|
|
1152
|
+
from Kafka raises `CompilationError` with `KAFKA_CONFIG_INVALID` naming the
|
|
1153
|
+
missing field. Before, a missing `delivery` resolved to `at_most_once`.
|
|
1154
|
+
Declare `delivery: at_most_once` to keep that behaviour, or
|
|
1155
|
+
`delivery: at_least_once`. `ConsumerSettings.effective_delivery()` is
|
|
1156
|
+
removed; read `ConsumerSettings.delivery`.
|
|
1157
|
+
- **streaming:** `ConsumerSettings.enable_auto_commit` is removed, together
|
|
1158
|
+
with the `DELIVERY_CONFLICT` compile code. The consumer settings forbid
|
|
1159
|
+
unknown fields, so a config that sets `enable_auto_commit` fails to decode
|
|
1160
|
+
(`KAFKA_CONFIG_INVALID`). Declare `delivery` instead: `enable_auto_commit:
|
|
1161
|
+
false` was `delivery: at_least_once`, and `true` was `delivery:
|
|
1162
|
+
at_most_once`.
|
|
1163
|
+
- **streaming:** `ConsumerSettings.poll_timeout_ms` is removed. The
|
|
1164
|
+
partitioned source ignored it and logged a deprecation warning; a config
|
|
1165
|
+
that sets it now fails to decode (`KAFKA_CONFIG_INVALID`). Remove the key;
|
|
1166
|
+
the partitioned source is tuned with `batch_size` and `poll_backoff_ms`.
|
|
1167
|
+
- **streaming:** `CompilationError` takes `CompilationIssue` values only;
|
|
1168
|
+
bare strings and the `StreamingErrorCode.UNSPECIFIED` code they became are
|
|
1169
|
+
removed. Build an issue from a `StreamingErrorCode` member with `.issue()`.
|
|
1170
|
+
- **streaming:** `CompilationError.errors` is removed. Read the messages from
|
|
1171
|
+
`CompilationError.issues` (`[issue.message for issue in error.issues]`).
|
|
1172
|
+
- **streaming:** an `IntoTable` sink section (`streaming.sinks.<name>`) with a
|
|
1173
|
+
key its backend does not read fails at compile with `SINK_CONFIG_INVALID`,
|
|
1174
|
+
naming every unknown key; on Delta this covers the keys under `staging`
|
|
1175
|
+
too, and a `staging` or `writer_properties` that is not a mapping is
|
|
1176
|
+
refused. Before, such a key was ignored. A SQLAlchemy sink that references a
|
|
1177
|
+
shared `database` reads no pool keys (`pool_size`, `echo`, ...) from its own
|
|
1178
|
+
section, so they are refused there; set them under `database.<name>`.
|
|
1179
|
+
A SQLAlchemy or ClickHouse sink section that sets both `url` and `database`
|
|
1180
|
+
is refused too, instead of one silently winning: a SQLAlchemy sink sets one
|
|
1181
|
+
or the other, and a ClickHouse sink takes its url from `database.<name>`, so
|
|
1182
|
+
it sets `database` only.
|
|
1183
|
+
Delta's `part_max_records` is removed and therefore refused: it was an alias
|
|
1184
|
+
of `writer_properties.max_row_group_size`, which is the key to set. Without
|
|
1185
|
+
`writer_properties` the row groups still hold at most 10 000 rows.
|
|
1186
|
+
`DeltaSinkConfig` has no `part_max_records` attribute.
|
|
1187
|
+
- **streaming:** `CompiledSingleSource` and `CompiledMultiSource` take a
|
|
1188
|
+
required `settings_key`, the config key their consumer settings were
|
|
1189
|
+
resolved from (`kafka.consumer` or `kafka.consumers.<ref>`);
|
|
1190
|
+
`KafkaSettings.consumer_key_for(ref)` names it.
|
|
962
1191
|
- **streaming:** `FromTopic`, `FromMultiTypeTopic`, `FromMongoCDC` and
|
|
963
1192
|
`IntoTopic` take no `shape`, `CompiledSingleSource`, `CompiledMultiSource`
|
|
964
1193
|
and `CompiledMongoCDCSource` have no `shape` field, and `StreamShape.MANY`
|
|
@@ -1088,11 +1317,71 @@
|
|
|
1088
1317
|
- **streaming:** a sync `With(process=...)` hands on one message at a time, as
|
|
1089
1318
|
`WithAsync` does. After a `CollectBatch` it handed on whole batches, so as
|
|
1090
1319
|
the last node of a flow without `output` its messages never completed.
|
|
1320
|
+
- **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds each column with
|
|
1321
|
+
the type core compiles for the field instead of its own map:
|
|
1322
|
+
- a `StrEnum` or `IntEnum` field is written as its scalar (`String`,
|
|
1323
|
+
`Integer`) instead of as JSON;
|
|
1324
|
+
- a column type declared with `ColumnField` (on a `BaseModel`) or
|
|
1325
|
+
`Annotated[T, <ColumnType>]` is used;
|
|
1326
|
+
- a `Decimal`, plain `Enum` or `Literal` field without a declared column
|
|
1327
|
+
type is refused when the partition is built, with core's message, instead
|
|
1328
|
+
of being written as `Numeric()` (a `Decimal`) or as JSON. Declare it, e.g.
|
|
1329
|
+
`Annotated[Decimal, Numeric(precision=12, scale=2)]`, or
|
|
1330
|
+
`Annotated[Decimal, Numeric()]` for an unbounded `NUMERIC`.
|
|
1331
|
+
- **streaming:** `IntoTable` with `Backend.CLICKHOUSE` hands a `date` field to
|
|
1332
|
+
clickhouse-connect as a `date`, as core keeps it for a column, instead of as
|
|
1333
|
+
its ISO-8601 text. clickhouse-connect writes a `Date` column only from a
|
|
1334
|
+
`date` and refused the text ("unsupported operand type(s) for -: 'str' and
|
|
1335
|
+
'datetime.date'"); a `String` column now refuses the `date` ("object of type
|
|
1336
|
+
'datetime.date' has no len()"). A `dict` value is written as compact JSON
|
|
1337
|
+
text from `msgspec.json`, keys still sorted (`{"a":1}`, was `{"a": 1}`).
|
|
1091
1338
|
|
|
1092
1339
|
## 🐛 Fixes
|
|
1093
1340
|
|
|
1094
1341
|
### core
|
|
1095
1342
|
|
|
1343
|
+
- **core:** `RepositoryDynamoDB` reads, updates and deletes by a `UUID`
|
|
1344
|
+
primary key. `get_by_id`, `get_by`, `exists_by`, `update` and `delete`
|
|
1345
|
+
handed the raw key to boto3's `TypeSerializer`, which raised
|
|
1346
|
+
`TypeError: Unsupported type "<class 'uuid.UUID'>"`; `create` already stored
|
|
1347
|
+
the key as a string through `msgspec.to_builtins`. The key is now encoded
|
|
1348
|
+
with that same conversion, so it matches its stored form and round-trips.
|
|
1349
|
+
`update` keeps the key as stored instead of rewriting it from the argument.
|
|
1350
|
+
Attribute values are encoded as before.
|
|
1351
|
+
- **cache:** security: the repository cache keeps each caller's entries apart.
|
|
1352
|
+
The entity key (`get_by_id`, and the rows behind a cached page), the
|
|
1353
|
+
`list_paginated` index key, the `list_with_query` key and the key of a
|
|
1354
|
+
`@cache_query` read (`scope="entity"` and `scope="list"`) now carry the
|
|
1355
|
+
caller's cache scope, so a row, a page of ids, a first page with its next
|
|
1356
|
+
cursor or a custom read's result cached for one caller is no longer served
|
|
1357
|
+
to another that row-level security hides it from. The scope comes from the
|
|
1358
|
+
new, provisional `SupportsCacheScope.cache_scope()` (`""` for a repository
|
|
1359
|
+
without it): `RepositorySQLAlchemy` builds it from every setting the
|
|
1360
|
+
session-settings provider returns, so a policy reading a product setting
|
|
1361
|
+
such as `app.tenant_id` is kept apart too, while cursor tokens stay bound to
|
|
1362
|
+
the `loom.scope.*` settings only. Inside a caller-owned transaction (the
|
|
1363
|
+
unit of work a use case runs in, or a `@transactional` scope) every cached
|
|
1364
|
+
read goes straight to the repository, with no lookup and no store, and so
|
|
1365
|
+
does a call to a `@cache_query` method whose `session` parameter, passed by
|
|
1366
|
+
position or by name, is not `None`. This holds where the backend reports
|
|
1367
|
+
such a transaction, SQLAlchemy and Mongo with transactions; DynamoDB and
|
|
1368
|
+
Mongo with `transactions: false` keep caching, and a read-only use case run
|
|
1369
|
+
outside another unit of work opens none and keeps using the cache. Writes
|
|
1370
|
+
still evict every scope's entries: the scope is not part of the dependency
|
|
1371
|
+
tags, and a write bumps the same generation counters whatever its scope. The
|
|
1372
|
+
scope is read once per cache operation and read again before its writes,
|
|
1373
|
+
which are skipped if it changed. `CachedRepository` implements
|
|
1374
|
+
`cache_scope()` and `has_caller_scoped_session()` by forwarding the wrapped
|
|
1375
|
+
repository's, so a wrapper around it keys by the same scope and stays out of
|
|
1376
|
+
the same transactions, and refuses at construction, with a `RuntimeError`, a
|
|
1377
|
+
repository whose `session_manager` has session settings but which does not
|
|
1378
|
+
implement `cache_scope()`. The list filter, query and `@cache_query`
|
|
1379
|
+
arguments fingerprints in cache keys are now the full SHA-256 instead of its
|
|
1380
|
+
first 64 bits. `entity_key` and `list_index_key` take a required
|
|
1381
|
+
keyword-only `scope`, and the new `query_index_key` and `custom_query_key`
|
|
1382
|
+
build the `list_with_query` and `@cache_query` keys. Existing entity, list,
|
|
1383
|
+
query and `@cache_query` entries are no longer read after the upgrade and
|
|
1384
|
+
expire by their TTL.
|
|
1096
1385
|
- **core:** one environment selector and deploy checks (ADR 0005). loom had
|
|
1097
1386
|
two unconnected notions of environment (the logger's `dev`/`prod`, where an
|
|
1098
1387
|
unknown value meant `dev`, and `FlowCtx.environment`) and nothing checked a
|
|
@@ -1143,10 +1432,25 @@
|
|
|
1143
1432
|
startup. `parse_environment` validates a value naming an environment.
|
|
1144
1433
|
- **core:** the SQLAlchemy query compiler converts a filter value, and each
|
|
1145
1434
|
`in` item, as the repository converts a value it writes
|
|
1146
|
-
(`loom.core.
|
|
1435
|
+
(`loom.core.model.convert.to_column_value`, now shared by
|
|
1147
1436
|
both): an `Enum` member is bound as its value, a JSON column's value is
|
|
1148
1437
|
reduced to builtins. A plain `Enum` member as the value of a filter on a
|
|
1149
1438
|
string column failed to bind.
|
|
1439
|
+
- **core:** pagination cursors are signed and decoded strictly (ADR 0004).
|
|
1440
|
+
A cursor token was base64url JSON with no integrity, and a datetime key
|
|
1441
|
+
decoded without a time zone, so a client could forge a position and a
|
|
1442
|
+
consumer comparing it with aware datetimes raised `TypeError` (a 500). A
|
|
1443
|
+
token is now `base64url(payload).base64url(tag)`, the tag an HMAC-SHA256
|
|
1444
|
+
over a domain-separated input bound to the model, the normalised filters,
|
|
1445
|
+
the sort and the caller's scope, verified with `hmac.compare_digest` before
|
|
1446
|
+
the payload is parsed. A malformed, unsigned, forged or rebound token, a
|
|
1447
|
+
key signed by an unknown key id, a datetime key without a time zone, a key
|
|
1448
|
+
of an unknown type, the wrong number of keys or the wrong backend is
|
|
1449
|
+
`UnsupportedQuery` (`400 unsupported_query`), and the message never echoes
|
|
1450
|
+
the token. A naive datetime key, such as a `DateTime(tz=False)` column, is
|
|
1451
|
+
issued as UTC with an explicit offset and compared as naive UTC against
|
|
1452
|
+
that column, on SQLite and Postgres alike.
|
|
1453
|
+
|
|
1150
1454
|
- **core:** a `BoundaryValidationError` no longer echoes the rejected value
|
|
1151
1455
|
(#347). msgspec's `Invalid enum value 'x'` (an `Enum`, `IntEnum` or `Literal`
|
|
1152
1456
|
field or dict key) and `Invalid value 'x'` (a tagged-union tag) become
|
|
@@ -1175,8 +1479,9 @@
|
|
|
1175
1479
|
column only. The cursor now orders and compares on
|
|
1176
1480
|
every key column after the sort keys and carries every key value in the
|
|
1177
1481
|
token; offset pages and `list_paginated` order by every key column too.
|
|
1178
|
-
|
|
1179
|
-
model keyed its entries by the first key column
|
|
1482
|
+
That fix leaves tokens of single-column keys as they were. A cached
|
|
1483
|
+
repository over such a model keyed its entries by the first key column
|
|
1484
|
+
too, so a warm
|
|
1180
1485
|
`list_paginated` or first cursor page served the rows sharing a first key
|
|
1181
1486
|
value as copies of one of them; it now caches and reloads every row by its
|
|
1182
1487
|
full key, one `get_by_id` per missing row.
|
|
@@ -1212,6 +1517,12 @@
|
|
|
1212
1517
|
|
|
1213
1518
|
### etl
|
|
1214
1519
|
|
|
1520
|
+
- **etl:** the error for a missing destination table names only advice that
|
|
1521
|
+
works under the policy in force. Under `missing_table_policy='error'` it
|
|
1522
|
+
used to suggest `SchemaMode.OVERWRITE`, which that policy ignores; it now
|
|
1523
|
+
suggests `missing_table_policy='create'`, `'schema_mode'` with
|
|
1524
|
+
`SchemaMode.OVERWRITE`, or creating the table first.
|
|
1525
|
+
|
|
1215
1526
|
- **etl:** `replace(allow_empty=False)` on Spark writes the rows it checked.
|
|
1216
1527
|
The writer ran `DataFrame.isEmpty()` and then let the write compute the
|
|
1217
1528
|
frame again, so a source that changed in between, or a nondeterministic
|
|
@@ -1392,6 +1703,11 @@
|
|
|
1392
1703
|
|
|
1393
1704
|
### streaming
|
|
1394
1705
|
|
|
1706
|
+
- **streaming:** `SINK_CANNOT_TRACK_COMMITS` and
|
|
1707
|
+
`INLINE_SINK_CANNOT_SKIP_COMMITS` point their `field` at the `delivery` of
|
|
1708
|
+
the consumer the source was bound through, `kafka.consumer.delivery` or
|
|
1709
|
+
`kafka.consumers.<ref>.delivery`, instead of `streaming.delivery`, which no
|
|
1710
|
+
config reads.
|
|
1395
1711
|
- **streaming:** `ForEach` accepts the batch a `BatchStep` produces, so
|
|
1396
1712
|
`CollectBatch → BatchStep → ForEach → IntoTopic` compiles; it failed with
|
|
1397
1713
|
`shape mismatch: expected many but got batch before ForEach`. Under
|
|
@@ -1482,6 +1798,49 @@
|
|
|
1482
1798
|
offset at the step, also when the batch holds several messages of one
|
|
1483
1799
|
offset that an earlier expanding node produced. The new return type is under
|
|
1484
1800
|
Behaviour changes.
|
|
1801
|
+
- **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds a `bytes` field as
|
|
1802
|
+
`LargeBinary` (`bytea` on Postgres). It bound it as text, which Postgres
|
|
1803
|
+
refused for a `bytea` column ("column is of type bytea but expression is of
|
|
1804
|
+
type character varying"). IntoTable now takes each column's type from core's
|
|
1805
|
+
model introspection (`loom.core.backend.sqlalchemy.sa_table_for`), the type
|
|
1806
|
+
a compiled model declares, and builds each row with core's new
|
|
1807
|
+
`loom.core.repository.sqlalchemy.values.to_column_row`, which converts and
|
|
1808
|
+
checks values as the repository does when it writes them: a plain `Enum` as
|
|
1809
|
+
its value, a struct in a JSON column as a dict, an `UNSET` value left out so
|
|
1810
|
+
the column's database default applies, also when other rows of the batch
|
|
1811
|
+
set it, and a `time` whose UTC offset its column cannot take refused with
|
|
1812
|
+
`BoundaryValidationError` (`boundary_validation`) instead of being written
|
|
1813
|
+
without the offset. Relation and projection fields are no longer columns
|
|
1814
|
+
for any backend: the SQLAlchemy and Delta rows included them and failed on
|
|
1815
|
+
their `UNSET` value, and the ClickHouse insert named them. A `date` or
|
|
1816
|
+
`time` field is bound as `Date` or `Time`, as core infers it, so it is
|
|
1817
|
+
written into a Postgres `date` or `time` column; it was bound as `String`
|
|
1818
|
+
and Postgres refused it ("column is of type date but expression is of type
|
|
1819
|
+
character varying").
|
|
1820
|
+
- **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
|
|
1821
|
+
refuses an `UNSET` column value when the item is written, with
|
|
1822
|
+
`BoundaryValidationError` (`boundary_validation`) naming the field and the
|
|
1823
|
+
table. Delta failed later, at a mini-batch or flush, with pyarrow's
|
|
1824
|
+
`ArrowInvalid`, and ClickHouse passed the `UNSET` object to
|
|
1825
|
+
clickhouse-connect's `insert`. Neither can leave a column out for one row as
|
|
1826
|
+
`Backend.SQLALCHEMY` does.
|
|
1827
|
+
- **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
|
|
1828
|
+
converts each column value as `Backend.SQLALCHEMY` and core's repository
|
|
1829
|
+
do, with `loom.core.model.convert.to_column_value`: a plain `Enum` becomes
|
|
1830
|
+
its value and a nested `msgspec.Struct` or `LoomStruct` a dict, also inside a
|
|
1831
|
+
list or a dict, while `bytes`, `datetime`, `date`, `time`, `Decimal` and
|
|
1832
|
+
`UUID` are kept. Delta refused an `Enum` or a struct with pyarrow's
|
|
1833
|
+
`ArrowInvalid` ("did not recognize Python value type when inferring an
|
|
1834
|
+
Arrow data type"); a nested struct is now a Delta struct column, as a `dict`
|
|
1835
|
+
field already was, and keeps its `datetime` and `Decimal` types.
|
|
1836
|
+
clickhouse-connect refused an `Enum` or a struct ("object of type ... has no
|
|
1837
|
+
len()") and `json.dumps` a `dict` holding a `Decimal` or `datetime` ("Object
|
|
1838
|
+
of type Decimal is not JSON serializable"); an `Enum` is now inserted as its
|
|
1839
|
+
value and a struct or `dict` as JSON text from `msgspec.json`, a `datetime`
|
|
1840
|
+
inside it as ISO-8601 text and a `Decimal` as decimal text.
|
|
1841
|
+
`to_column_value` moved to `loom.core.model.convert` (under Behaviour
|
|
1842
|
+
changes), so the Delta and ClickHouse writers use it without SQLAlchemy
|
|
1843
|
+
installed.
|
|
1485
1844
|
|
|
1486
1845
|
### prefect
|
|
1487
1846
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: loom-kernel
|
|
3
|
-
Version:
|
|
3
|
+
Version: 9.0.0
|
|
4
4
|
Summary: Loom Python project
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -457,6 +457,10 @@ app:
|
|
|
457
457
|
title: My Store API
|
|
458
458
|
version: 0.1.0
|
|
459
459
|
|
|
460
|
+
persistence:
|
|
461
|
+
cursors:
|
|
462
|
+
signing: ephemeral # development.yaml only; production.yaml configures keys
|
|
463
|
+
|
|
460
464
|
database:
|
|
461
465
|
url: ${oc.env:DATABASE_URL,sqlite+aiosqlite:///store.db}
|
|
462
466
|
|
|
@@ -115,9 +115,7 @@ class _UsecaseGrant:
|
|
|
115
115
|
def _grant(key: str, use_case: type[Compilable]) -> _UsecaseGrant:
|
|
116
116
|
execution = use_case.__execution_plan__
|
|
117
117
|
if execution is None:
|
|
118
|
-
raise AgentCompilationError(
|
|
119
|
-
[f"use case '{key}' carries no compiled execution plan; it was never compiled"]
|
|
120
|
-
)
|
|
118
|
+
raise AgentCompilationError([AgentErrorCode.USECASE_NOT_COMPILED.issue(key=key)])
|
|
121
119
|
return _UsecaseGrant(
|
|
122
120
|
tool_name=tool_name("usecase", key), key=key, use_case=use_case, execution=execution
|
|
123
121
|
)
|
|
@@ -637,7 +635,11 @@ def _build(plan: AgentPlan, destination: _Destination, context: BuildContext) ->
|
|
|
637
635
|
binding = _KINDS.get(type(capability))
|
|
638
636
|
if binding is None:
|
|
639
637
|
raise AgentCompilationError(
|
|
640
|
-
[
|
|
638
|
+
[
|
|
639
|
+
AgentErrorCode.CAPABILITY_KIND_NO_BUILDER.issue(
|
|
640
|
+
component=context.agent, kind=capability.kind
|
|
641
|
+
)
|
|
642
|
+
]
|
|
641
643
|
)
|
|
642
644
|
if binding.destination is destination:
|
|
643
645
|
yield binding.builder(capability, context)
|
|
@@ -304,17 +304,6 @@ def _stdio_transport(command: str, capability: CompiledMcpCapability) -> ClientT
|
|
|
304
304
|
)
|
|
305
305
|
|
|
306
306
|
|
|
307
|
-
def _unopened_connection(agent: str, server: str) -> str:
|
|
308
|
-
"""Describe the wiring that would give an agent an unvalidated connection."""
|
|
309
|
-
return (
|
|
310
|
-
f"{agent}: the runtime never opened mcp server '{server}' through this engine's "
|
|
311
|
-
f"shared toolsets. The runtime's 'mcp_client_factory' must be the "
|
|
312
|
-
f"'mcp_client_factory' of the very provider instance that builds the engines, "
|
|
313
|
-
f"or the run would hold a second connection whose tool filters start-up never "
|
|
314
|
-
f"validated"
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
|
|
318
307
|
class SharedMcpToolsets:
|
|
319
308
|
"""The MCP toolsets of one worker: one per distinct connection.
|
|
320
309
|
|
|
@@ -408,7 +397,13 @@ class SharedMcpToolsets:
|
|
|
408
397
|
"""
|
|
409
398
|
connection = mcp_connection(capability)
|
|
410
399
|
if connection not in self._opened:
|
|
411
|
-
raise AgentCompilationError(
|
|
400
|
+
raise AgentCompilationError(
|
|
401
|
+
[
|
|
402
|
+
AgentErrorCode.MCP_CONNECTION_NOT_OPENED.issue(
|
|
403
|
+
component=agent, server=capability.server
|
|
404
|
+
)
|
|
405
|
+
]
|
|
406
|
+
)
|
|
412
407
|
return self._toolset(connection)
|
|
413
408
|
|
|
414
409
|
def _toolset(self, connection: CompiledMcpCapability) -> MCPToolset[Any]:
|