loom-kernel 8.0.0__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.0 → loom_kernel-9.0.0}/CHANGELOG.md +434 -26
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/PKG-INFO +5 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/README.md +4 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +6 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +7 -12
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +11 -6
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +3 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/errors.py +48 -10
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_lifecycle.py +5 -6
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/bootstrap.py +15 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/cli/check.py +1 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/backend/sqlalchemy.py +32 -4
- {loom_kernel-8.0.0 → 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.0 → loom_kernel-9.0.0}/src/loom/core/cache/repository.py +263 -148
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/result_codec.py +5 -29
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/checks.py +14 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/keys.py +2 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/overrides.py +15 -7
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/executor.py +1 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/environment.py +21 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/__init__.py +2 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/convert.py +31 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/field.py +9 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/introspection.py +60 -12
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/timestamped.py +0 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/types.py +11 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/types_postgres.py +1 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/plugins/entrypoints.py +5 -13
- {loom_kernel-8.0.0 → 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.0 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/repository.py +7 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/backend.py +11 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/ids.py +6 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/registry.py +19 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/repository.py +57 -27
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/backend.py +10 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/mixins.py +37 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +55 -14
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +34 -12
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/registry.py +25 -8
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/repository.py +17 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/session_manager.py +8 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/values.py +47 -31
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/__init__.py +1 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/compute.py +2 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/invoker.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/rule.py +6 -11
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/__init__.py +4 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/_policy.py +2 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_write_policy.py +13 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_reader.py +0 -6
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_schema.py +1 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_writer.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_schema.py +1 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_writer.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/__init__.py +0 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_cleaners.py +3 -7
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_store.py +2 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_filter.py +2 -30
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/_with_agent.py +5 -16
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_specs.py +0 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/__init__.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_builder.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_spec.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_into.py +5 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_table.py +1 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_clickhouse.py +2 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/__init__.py +1 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/core.py +1 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/schema/_schema.py +11 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_discovery.py +4 -2
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/compiler.py +161 -50
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/app.py +15 -49
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/auto.py +2 -1
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/openapi.py +8 -18
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/router_runtime.py +10 -6
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/model.py +8 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_adapter.py +35 -9
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_runtime_io.py +3 -7
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/runner.py +6 -5
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_errors.py +6 -17
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_plan.py +18 -19
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/phases/build_plan.py +14 -10
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/phases/validate.py +93 -110
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_config.py +20 -28
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_boundary.py +0 -7
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_mongo.py +0 -3
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_shape.py +3 -4
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_step.py +4 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/common.py +206 -159
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/config.py +21 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/repository_harness.py +7 -1
- loom_kernel-8.0.0/src/loom/core/cache/keys.py +0 -96
- loom_kernel-8.0.0/src/loom/core/repository/abc/cursor.py +0 -157
- loom_kernel-8.0.0/src/loom/core/repository/abc/session_scope.py +0 -37
- loom_kernel-8.0.0/src/loom/etl/declarative/target/_schema_mode.py +0 -5
- loom_kernel-8.0.0/src/loom/etl/runner/errors.py +0 -7
- loom_kernel-8.0.0/src/loom/etl/runner/filtering.py +0 -41
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/.gitignore +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/LICENSE +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/pyproject.toml +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_concurrency.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_filters.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_paths.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_roles.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_startup.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_transport.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/_usecase.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/_binding.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/_handlers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/_rpc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/card.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/events.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/a2a/server.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/abc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/bootstrap.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/_plan.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_capabilities.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_output.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/compiler/phases/_state.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/declarative/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/declarative/_envelope.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/declarative/_schema.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/declarative/_v1.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/describe.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_batch.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_columns.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_frames.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_ledger.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_runner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/etl/_validation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/fastapi/endpoints.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/fastapi/response.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/fastapi/streaming.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/inference.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/pricing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/remote_auth.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_bounded.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_chain.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_conversation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_grants.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_handle.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_health.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_hooks.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_limits.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/runtime/_mcp.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/validate/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/ai/validate/__main__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/auto.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/constants.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/runner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/celery/service.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/cli/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/cli/app.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/cli/schema.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/async_bridge.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/_decide.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/_grants.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/_roles.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/_scope.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/elevation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/authz/product.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/backend/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/backend/core_model.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/backend/protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/backend/scoped_ddl.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/bootstrap/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/bootstrap/kernel.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/_batching.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/_single_flight.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/abc/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/abc/backend.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/abc/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/abc/dependency.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/calls.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/codec.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/dependency.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/gateway.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/memory.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/serializer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/cache/wiring.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/command/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/command/adapter.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/command/base.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/command/field.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/command/introspection.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/_boto3.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/_includes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/_resolver_utils.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/binder.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/configurable.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/context.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/loader.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/model.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/observability.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/resolver.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/secrets.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/config/ssm.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/contracts/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/contracts/manifest.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/di/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/di/container.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/di/scope.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/_utils.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/base.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/interfaces.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/manifest.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/discovery/modules.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/compilable.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/events.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/metrics.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/plan.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/engine/post_commit.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/errors/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/errors/codes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/errors/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/expr/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/expr/eval.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/expr/nodes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/expr/refs.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/identity/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/identity/context.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/identity/identity.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/identity/issuer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/identity/wire.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/introspection/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/introspection/base.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/introspection/describe.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/callback.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/context.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/handle.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/job.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/job/service.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/locator.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/abc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/checks.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/logger/structlogger.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/_json_schema.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/_loom_type.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/base.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/enums.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/partition.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/privilege.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/projection.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/relation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/scoped.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/model/struct.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/event.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/observer/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/observer/noop.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/observer/otel.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/observer/structlog.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/otel_ids.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/runtime.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/span.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/observability/topology.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/persistence/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/persistence/abc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/persistence/none.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/persistence/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/plugins/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/plugins/optional.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/projection/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/projection/loaders.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/projection/runtime.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/abc/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/abc/query.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/abc/repo_for.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/abc/repository.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/backend.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/uow.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mongo/values.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/mutation.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/registration.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/response/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/response/base.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/routing/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/routing/ref.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/routing/resolver.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/runner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/schema/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/schema/schema_mode.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/schema_names.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/abc/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/abc/contracts.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/abc/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/caller_bound.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/_client.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/clickhouse/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/roles.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/sql/service.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/symbols.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/tracing/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/tracing/context.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/transaction.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/transport/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/transport/adapter.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/uow/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/uow/abc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/uow/context.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/_predicates.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/agent_markers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/constants.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/factory.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/field_ref.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/keys.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/markers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/mcp_markers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/outcome.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/core/use_case/use_case.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/_uri.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_format_registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_common.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_log.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_merge.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_path_template.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_predicate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_frame.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_historify.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/polars/provider.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_historify.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_reader.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/backends/spark/provider.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_options.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_paths.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/checkpoint/_scope.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_binding.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_plan.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_plan.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/compiler/_validators_step.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/_format.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/_read_options.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/_utils.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/_write_options.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_params.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_client.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_file.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/declarative/target/_temp.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/executor/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/executor/_agents.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/executor/_dispatcher.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/executor/_executor.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/_registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/sources/_serialization.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/targets/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/io/targets/_clickhouse.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/_observer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/_records.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_builder.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_ops.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_runner.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/_step.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_generics.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_params.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_process.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_sql.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step_client.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/_agents.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/_providers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/_wiring.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runner/config_loader.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runtime/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runtime/_config_values.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/runtime/contracts.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/schema/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/schema/_contract.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/storage/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/storage/_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/storage/_file_locator.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/storage/_locator.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/storage/routing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/_result.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/_runners.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/_scenario.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/_stubs.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/etl/testing/spark.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_async.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_ctx.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_flow_yaml.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_meta.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_placeholders.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/_summary.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/deploy/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_schedule.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_assemble.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_backfill.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_body.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_common.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_factory.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_hooks.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_maintenance.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_params.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_run_name.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_runtime.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_signature.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/flow/_stages.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/manifest/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_model.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_s3.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/manifest/_store.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_event.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_factory.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_format.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_port.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_slack.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/notify/_sns.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/observer/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/observer/_flow.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/observer/_manifest.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prefect/observer/_task_run.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/_instruments.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/adapter.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/kafka.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/lifecycle.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/prometheus/middleware.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/py.typed +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/_body.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/adapter.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/auth/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/auth/abc.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/auth/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/auth/jwt.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/auth/middleware.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/autocrud.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/checks.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/constants.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/cors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/health.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/response.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/fastapi/sql.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/middleware.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/rest/rest_adapter.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_operators.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/_shared.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_bindings.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/compiler/_compiler.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/_exceptions.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/_message.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/_tracing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/core/_typing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/graph/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/graph/_flow.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_codec.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_errors.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_message.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_record.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/_wire.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/mongo/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_config.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_event.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/mongo/_normalize.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_branches.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_decompose.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_fork.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_helpers.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_protocols.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_router.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_sink.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_table/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/_with.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/nodes/refs.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/streaming/testing.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/__init__.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/agents.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/golden.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/http_harness.py +0 -0
- {loom_kernel-8.0.0 → loom_kernel-9.0.0}/src/loom/testing/in_memory.py +0 -0
- {loom_kernel-8.0.0 → 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,78 @@
|
|
|
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.
|
|
524
|
+
- **core:** a `Decimal` field, plain or optional, declares its column type: a
|
|
525
|
+
SQLAlchemy model with an undeclared one is refused when it is compiled,
|
|
526
|
+
naming the field. loom inferred `NUMERIC(10, 2)`, and Postgres silently
|
|
527
|
+
rounds a value to that scale (`1.2345` is stored as `1.23`) and refuses one
|
|
528
|
+
past that precision. Migration: declare it, e.g.
|
|
529
|
+
`Annotated[Decimal, Numeric(precision=20, scale=6)]` or
|
|
530
|
+
`ColumnField(Numeric(precision=20, scale=6))`; `Numeric()` with no
|
|
531
|
+
precision is now an unbounded `NUMERIC` instead of `NUMERIC(10, 2)`, and
|
|
532
|
+
`Numeric(scale=...)` without a precision raises `ValueError`, as SQLAlchemy
|
|
533
|
+
would drop the scale.
|
|
462
534
|
- **core:** `sql_endpoint.auth` admits only `identity` and `external`;
|
|
463
535
|
`auth: jwt` is refused when the config is loaded, and the alias and its
|
|
464
536
|
`DeprecationWarning` are gone. Migration: replace `auth: jwt` with
|
|
@@ -550,6 +622,81 @@
|
|
|
550
622
|
or `RuleViolation` it returns no longer fails the rule. Migrate
|
|
551
623
|
`Rule.check(F(Order).total, via=lambda v: v <= 0, message="total must be > 0")`
|
|
552
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
|
+
|
|
553
700
|
- **core:** the `LoomType` protocol gains `from_query(params)`, which
|
|
554
701
|
validates query-string values strictly. A number takes the JSON number
|
|
555
702
|
grammar and must be finite, an integer its integer subset within
|
|
@@ -567,8 +714,7 @@
|
|
|
567
714
|
takes the tuple as its first argument and raises `TypeError` for anything
|
|
568
715
|
else. A cursor token issued for such a model before this release is refused with
|
|
569
716
|
`UnsupportedQuery`, `400 unsupported_query`; clients restart from the first
|
|
570
|
-
page. `
|
|
571
|
-
`get_id_attributes` returns every key column name.
|
|
717
|
+
page. `get_id_attributes` returns every key column name.
|
|
572
718
|
|
|
573
719
|
- **core:** `compile_all` raises `ValueError` for a model with a composite
|
|
574
720
|
primary key that declares a relation or a projection whose loader runs
|
|
@@ -663,6 +809,8 @@
|
|
|
663
809
|
present convert those rows deliberately (for example to UTC with
|
|
664
810
|
`(c::timetz AT TIME ZONE 'UTC')::time`) before changing the type. MongoDB is
|
|
665
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`.
|
|
666
814
|
|
|
667
815
|
### ai
|
|
668
816
|
|
|
@@ -671,9 +819,15 @@
|
|
|
671
819
|
example `spec_malformed`, `engine_not_found` and `mcp_server_unreachable`.
|
|
672
820
|
Build an issue with `AgentErrorCode.X.issue(...)` and keyword arguments,
|
|
673
821
|
such as `AgentErrorCode.ENGINE_NOT_FOUND.issue(component="openai-agents",
|
|
674
|
-
available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too
|
|
675
|
-
|
|
676
|
-
|
|
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`.
|
|
677
831
|
- **ai:** `AgentCompilationIssue` is a type alias of
|
|
678
832
|
`CompileIssue[AgentErrorCode]` from `loom.core.errors.codes`, not a class.
|
|
679
833
|
It has the same fields, but `isinstance` against it raises `TypeError`
|
|
@@ -752,6 +906,9 @@
|
|
|
752
906
|
declares both a pydantic `type_ref` output and `output_check` serialises
|
|
753
907
|
an accepted answer twice per attempt — once for the check's own builtins
|
|
754
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.
|
|
755
912
|
|
|
756
913
|
### rest
|
|
757
914
|
|
|
@@ -814,6 +971,33 @@
|
|
|
814
971
|
`msgspec.ValidationError`. The root `title` is dropped on pydantic
|
|
815
972
|
OpenAPI schemas for request bodies and responses alike, matching the
|
|
816
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`, ...).
|
|
817
1001
|
|
|
818
1002
|
### prefect
|
|
819
1003
|
|
|
@@ -904,11 +1088,8 @@
|
|
|
904
1088
|
- **etl:** a `WithAgent` compiled by a runner whose config has no `ai:`
|
|
905
1089
|
section fails with the new code `AGENT_RUNNER_NOT_CONFIGURED` instead of
|
|
906
1090
|
`AGENT_NOT_FOUND`, which now means only that no artifact declares the name.
|
|
907
|
-
- **etl:**
|
|
908
|
-
`
|
|
909
|
-
`_map_process_nodes`) are deprecated and removed in loom 3.0; each emits a
|
|
910
|
-
`DeprecationWarning` naming its replacement, `loom.etl.compiler.filter_plan`
|
|
911
|
-
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`.
|
|
912
1093
|
- **etl:** the Polars writer refuses, under `SchemaMode.STRICT` and
|
|
913
1094
|
`EVOLVE`, a frame column that is a `Struct` or `List` where the Delta table
|
|
914
1095
|
has `String`, or `String` where the table has a `Struct` or `List`, at any
|
|
@@ -927,8 +1108,7 @@
|
|
|
927
1108
|
`Unknown step or process names: [...]` instead of `No steps or processes
|
|
928
1109
|
match include=[...]`, the constructor's parameter is `unknown`, and the
|
|
929
1110
|
names are kept on the new `unknown` attribute. Positional construction is
|
|
930
|
-
unchanged
|
|
931
|
-
`DeprecationWarning` and is removed in loom 3.0. The error survives pickle
|
|
1111
|
+
unchanged. The error survives pickle
|
|
932
1112
|
with its `unknown` names, so it crosses process boundaries intact.
|
|
933
1113
|
- **etl:** `ThreadDispatcher` runs each task in a copy of the caller's
|
|
934
1114
|
context, as `asyncio.to_thread` does, so a step of a parallel group sees
|
|
@@ -939,16 +1119,91 @@
|
|
|
939
1119
|
caller's context among the requirements on an implementation.
|
|
940
1120
|
- **etl:** `WithAgent(max_usd=...)` keeps the budget as a `Decimal`. An
|
|
941
1121
|
`int`, or another `numbers.Integral` such as `numpy.int64`, is converted
|
|
942
|
-
exactly. A `
|
|
943
|
-
`
|
|
944
|
-
|
|
945
|
-
`
|
|
946
|
-
|
|
947
|
-
`
|
|
948
|
-
|
|
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`).
|
|
949
1147
|
|
|
950
1148
|
### streaming
|
|
951
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.
|
|
1191
|
+
- **streaming:** `FromTopic`, `FromMultiTypeTopic`, `FromMongoCDC` and
|
|
1192
|
+
`IntoTopic` take no `shape`, `CompiledSingleSource`, `CompiledMultiSource`
|
|
1193
|
+
and `CompiledMongoCDCSource` have no `shape` field, and `StreamShape.MANY`
|
|
1194
|
+
is removed. The runtime never read a declared shape: every source emits one
|
|
1195
|
+
record per message, so a source declared `BATCH` was shape-checked as
|
|
1196
|
+
batches while its nodes received records, and an `IntoTopic` writes one
|
|
1197
|
+
record per message whatever it declared. Every flow now starts as a record
|
|
1198
|
+
stream, and an `IntoTopic` ends its path (shape `none`). Migration: drop
|
|
1199
|
+
`shape=`; to work on batches, use `CollectBatch` and, back to records,
|
|
1200
|
+
`ForEach`.
|
|
1201
|
+
- **streaming:** a batch reaching a `Drain` or a `Broadcast` fails compilation
|
|
1202
|
+
with `SHAPE_MISMATCH`, whatever the delivery. Under at-most-once delivery
|
|
1203
|
+
`CollectBatch → Drain` compiled and dropped the batch; under at-least-once
|
|
1204
|
+
the batch's offsets never completed. Under at-least-once a `Broadcast` with
|
|
1205
|
+
more than one route raised `TypeError` (`Expected Message, got list`) on a
|
|
1206
|
+
batch. Put a `ForEach` before the node.
|
|
952
1207
|
- **streaming:** `BatchExpandStep.execute` returns one list of payloads per
|
|
953
1208
|
message of its batch, in batch order, instead of one flat list. List `i`
|
|
954
1209
|
holds what `messages[i]` expands into; each output takes that message's
|
|
@@ -975,9 +1230,11 @@
|
|
|
975
1230
|
`CompileIssue` instead), `loom_message_type()` is gone, and
|
|
976
1231
|
`CompilationIssue.prefixed()` is removed. Messages keep their text.
|
|
977
1232
|
- **streaming:** a `Broadcast` followed by another node reports
|
|
978
|
-
`BROADCAST_NOT_LAST` with component `broadcast`, at the top level
|
|
979
|
-
branch
|
|
980
|
-
|
|
1233
|
+
`BROADCAST_NOT_LAST` with component `broadcast`, at the top level and in a
|
|
1234
|
+
branch. It used to report `TERMINAL_NOT_LAST` with component `Broadcast`. In
|
|
1235
|
+
a Router branch a `Broadcast` reports `ROUTER_BRANCH_UNSAFE_NODE`, and one
|
|
1236
|
+
followed by another node also `TERMINAL_NOT_LAST` with component
|
|
1237
|
+
`router branch <label> > Broadcast`.
|
|
981
1238
|
- **streaming:** a Router branch that ends in `IntoTopic`, `IntoTable` (any
|
|
982
1239
|
`IntoSink`) or `Drain` hands the message to that terminal. The branch's
|
|
983
1240
|
terminal was skipped: with a flow `output` the message went to the output
|
|
@@ -1060,11 +1317,71 @@
|
|
|
1060
1317
|
- **streaming:** a sync `With(process=...)` hands on one message at a time, as
|
|
1061
1318
|
`WithAsync` does. After a `CollectBatch` it handed on whole batches, so as
|
|
1062
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}`).
|
|
1063
1338
|
|
|
1064
1339
|
## 🐛 Fixes
|
|
1065
1340
|
|
|
1066
1341
|
### core
|
|
1067
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.
|
|
1068
1385
|
- **core:** one environment selector and deploy checks (ADR 0005). loom had
|
|
1069
1386
|
two unconnected notions of environment (the logger's `dev`/`prod`, where an
|
|
1070
1387
|
unknown value meant `dev`, and `FlowCtx.environment`) and nothing checked a
|
|
@@ -1115,10 +1432,25 @@
|
|
|
1115
1432
|
startup. `parse_environment` validates a value naming an environment.
|
|
1116
1433
|
- **core:** the SQLAlchemy query compiler converts a filter value, and each
|
|
1117
1434
|
`in` item, as the repository converts a value it writes
|
|
1118
|
-
(`loom.core.
|
|
1435
|
+
(`loom.core.model.convert.to_column_value`, now shared by
|
|
1119
1436
|
both): an `Enum` member is bound as its value, a JSON column's value is
|
|
1120
1437
|
reduced to builtins. A plain `Enum` member as the value of a filter on a
|
|
1121
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
|
+
|
|
1122
1454
|
- **core:** a `BoundaryValidationError` no longer echoes the rejected value
|
|
1123
1455
|
(#347). msgspec's `Invalid enum value 'x'` (an `Enum`, `IntEnum` or `Literal`
|
|
1124
1456
|
field or dict key) and `Invalid value 'x'` (a tagged-union tag) become
|
|
@@ -1147,8 +1479,9 @@
|
|
|
1147
1479
|
column only. The cursor now orders and compares on
|
|
1148
1480
|
every key column after the sort keys and carries every key value in the
|
|
1149
1481
|
token; offset pages and `list_paginated` order by every key column too.
|
|
1150
|
-
|
|
1151
|
-
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
|
|
1152
1485
|
`list_paginated` or first cursor page served the rows sharing a first key
|
|
1153
1486
|
value as copies of one of them; it now caches and reloads every row by its
|
|
1154
1487
|
full key, one `get_by_id` per missing row.
|
|
@@ -1184,6 +1517,12 @@
|
|
|
1184
1517
|
|
|
1185
1518
|
### etl
|
|
1186
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
|
+
|
|
1187
1526
|
- **etl:** `replace(allow_empty=False)` on Spark writes the rows it checked.
|
|
1188
1527
|
The writer ran `DataFrame.isEmpty()` and then let the write compute the
|
|
1189
1528
|
frame again, so a source that changed in between, or a nondeterministic
|
|
@@ -1364,6 +1703,32 @@
|
|
|
1364
1703
|
|
|
1365
1704
|
### streaming
|
|
1366
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.
|
|
1711
|
+
- **streaming:** `ForEach` accepts the batch a `BatchStep` produces, so
|
|
1712
|
+
`CollectBatch → BatchStep → ForEach → IntoTopic` compiles; it failed with
|
|
1713
|
+
`shape mismatch: expected many but got batch before ForEach`. Under
|
|
1714
|
+
at-least-once delivery each offset completes once, after its write is
|
|
1715
|
+
flushed.
|
|
1716
|
+
- **streaming:** a batch reaching a node that takes records fails compilation
|
|
1717
|
+
with `SHAPE_MISMATCH`: `IntoTopic`, `IntoTable` (any `IntoSink`), `Fork`,
|
|
1718
|
+
`ExpandRoutes`, `CollectBatch` (it groups records), the flow `output`
|
|
1719
|
+
(component `flow.output`, field `output`)
|
|
1720
|
+
and a Broadcast route `output` (component `broadcast branch <n> > output`,
|
|
1721
|
+
field `output`). Such flows used to compile. `CollectBatch → BatchStep →
|
|
1722
|
+
IntoTopic` raised `'list' object has no attribute 'meta'` at runtime. Put a
|
|
1723
|
+
`ForEach` before the node. `Drain` and `Broadcast` are under Behaviour
|
|
1724
|
+
changes.
|
|
1725
|
+
- **streaming:** a `BatchExpandStep` subclass outputs records to the shape
|
|
1726
|
+
check. The compiler matched step output shapes by exact type, so every step
|
|
1727
|
+
subclass kept the incoming shape and a record step after a
|
|
1728
|
+
`BatchExpandStep` failed with `expected record but got batch`. The shape
|
|
1729
|
+
check reads a step's `input_shape` and `output_shape` from its class,
|
|
1730
|
+
except in a Router branch: there a `BatchStep` runs one record at a time,
|
|
1731
|
+
on a one-message batch, so it is record to record.
|
|
1367
1732
|
- **streaming:** a `Broadcast` is validated as a `Broadcast`. The compiler
|
|
1368
1733
|
treated it as a plain terminal, so the nodes of its branches were never
|
|
1369
1734
|
shape-checked. A branch with a shape mismatch, such as a record step after
|
|
@@ -1433,6 +1798,49 @@
|
|
|
1433
1798
|
offset at the step, also when the batch holds several messages of one
|
|
1434
1799
|
offset that an earlier expanding node produced. The new return type is under
|
|
1435
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.
|
|
1436
1844
|
|
|
1437
1845
|
### prefect
|
|
1438
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)
|