loom-kernel 8.0.1__tar.gz → 9.1.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.
Files changed (735) hide show
  1. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/CHANGELOG.md +441 -29
  2. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/PKG-INFO +5 -1
  3. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/README.md +4 -0
  4. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/card.py +1 -1
  5. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/server.py +4 -1
  6. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_plan.py +12 -7
  7. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_capabilities.py +17 -6
  8. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/config.py +38 -23
  9. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +6 -4
  10. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +13 -13
  11. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +11 -6
  12. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +14 -2
  13. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +2 -2
  14. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +2 -2
  15. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +2 -2
  16. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +2 -2
  17. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/errors.py +48 -10
  18. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/inference.py +2 -1
  19. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/remote_auth.py +9 -3
  20. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_lifecycle.py +5 -6
  21. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/bootstrap.py +53 -38
  22. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/config.py +6 -5
  23. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/check.py +1 -0
  24. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/sqlalchemy.py +24 -0
  25. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/config.py +5 -2
  26. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/decorators.py +4 -5
  27. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/gateway.py +3 -1
  28. loom_kernel-9.1.0/src/loom/core/cache/keys.py +186 -0
  29. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/repository.py +263 -148
  30. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/result_codec.py +5 -29
  31. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/checks.py +21 -4
  32. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/__init__.py +2 -0
  33. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/_resolver_utils.py +10 -12
  34. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/binder.py +4 -3
  35. loom_kernel-9.1.0/src/loom/core/config/checks.py +64 -0
  36. loom_kernel-9.1.0/src/loom/core/config/convert.py +206 -0
  37. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/keys.py +2 -0
  38. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/loader.py +2 -1
  39. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/observability.py +13 -7
  40. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/overrides.py +31 -9
  41. loom_kernel-9.1.0/src/loom/core/config/retired.py +35 -0
  42. loom_kernel-9.1.0/src/loom/core/connections/__init__.py +40 -0
  43. loom_kernel-9.1.0/src/loom/core/connections/_base.py +134 -0
  44. loom_kernel-9.1.0/src/loom/core/connections/aws/__init__.py +12 -0
  45. loom_kernel-9.1.0/src/loom/core/connections/aws/client.py +51 -0
  46. loom_kernel-9.1.0/src/loom/core/connections/aws/config.py +91 -0
  47. loom_kernel-9.1.0/src/loom/core/connections/aws/loader.py +35 -0
  48. loom_kernel-9.1.0/src/loom/core/connections/clickhouse/__init__.py +12 -0
  49. loom_kernel-9.1.0/src/loom/core/connections/clickhouse/client.py +83 -0
  50. loom_kernel-9.1.0/src/loom/core/connections/clickhouse/config.py +77 -0
  51. loom_kernel-9.1.0/src/loom/core/connections/clickhouse/loader.py +44 -0
  52. loom_kernel-9.1.0/src/loom/core/connections/mongo/__init__.py +12 -0
  53. loom_kernel-9.1.0/src/loom/core/connections/mongo/client.py +64 -0
  54. loom_kernel-9.1.0/src/loom/core/connections/mongo/config.py +112 -0
  55. loom_kernel-9.1.0/src/loom/core/connections/mongo/loader.py +41 -0
  56. loom_kernel-9.1.0/src/loom/core/connections/relational.py +27 -0
  57. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/executor.py +1 -2
  58. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/environment.py +21 -4
  59. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/__init__.py +2 -0
  60. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/errors.py +4 -0
  61. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/locator.py +10 -54
  62. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/__init__.py +2 -0
  63. loom_kernel-9.1.0/src/loom/core/logger/context.py +43 -0
  64. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/__init__.py +2 -0
  65. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/_loom_type.py +5 -4
  66. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/convert.py +31 -1
  67. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/field.py +9 -4
  68. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/introspection.py +50 -8
  69. loom_kernel-9.1.0/src/loom/core/model/redaction.py +508 -0
  70. loom_kernel-9.1.0/src/loom/core/model/struct.py +112 -0
  71. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/timestamped.py +0 -2
  72. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/types.py +4 -0
  73. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/types_postgres.py +1 -0
  74. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/config.py +2 -1
  75. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/otel.py +15 -7
  76. loom_kernel-9.1.0/src/loom/core/persistence/__init__.py +46 -0
  77. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/abc.py +31 -11
  78. loom_kernel-9.1.0/src/loom/core/persistence/database.py +265 -0
  79. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/none.py +14 -7
  80. loom_kernel-9.1.0/src/loom/core/persistence/profile.py +119 -0
  81. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/entrypoints.py +5 -13
  82. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/__init__.py +21 -4
  83. loom_kernel-9.1.0/src/loom/core/repository/abc/checks.py +60 -0
  84. loom_kernel-9.1.0/src/loom/core/repository/abc/cursor.py +682 -0
  85. loom_kernel-9.1.0/src/loom/core/repository/abc/session_scope.py +60 -0
  86. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/backend.py +50 -47
  87. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/registry.py +8 -0
  88. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/repository.py +58 -15
  89. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/backend.py +44 -34
  90. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/ids.py +6 -2
  91. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/registry.py +19 -2
  92. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/repository.py +57 -27
  93. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/__init__.py +2 -1
  94. loom_kernel-9.1.0/src/loom/core/repository/sqlalchemy/_pool_metrics.py +42 -0
  95. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/backend.py +86 -76
  96. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +2 -1
  97. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/mixins.py +39 -6
  98. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +56 -15
  99. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +34 -12
  100. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/registry.py +25 -8
  101. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/repository.py +17 -2
  102. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +1 -1
  103. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/session_manager.py +89 -54
  104. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/values.py +47 -31
  105. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/_client.py +8 -31
  106. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/registry.py +10 -18
  107. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/config.py +62 -30
  108. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/__init__.py +1 -3
  109. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/compute.py +2 -2
  110. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/invoker.py +1 -1
  111. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/rule.py +6 -11
  112. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/__init__.py +8 -3
  113. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_merge.py +43 -3
  114. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/_policy.py +2 -2
  115. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_write_policy.py +78 -21
  116. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_reader.py +0 -6
  117. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_schema.py +1 -2
  118. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_writer.py +94 -4
  119. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/provider.py +32 -41
  120. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_schema.py +1 -2
  121. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_writer.py +4 -2
  122. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/provider.py +3 -2
  123. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/__init__.py +0 -2
  124. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_cleaners.py +3 -7
  125. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_store.py +2 -2
  126. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_compiler.py +11 -2
  127. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_errors.py +8 -0
  128. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_filter.py +2 -30
  129. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators.py +1 -15
  130. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_plan.py +6 -2
  131. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_step.py +21 -2
  132. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/__init__.py +4 -0
  133. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_with_agent.py +5 -16
  134. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -4
  135. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_specs.py +0 -5
  136. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/__init__.py +10 -2
  137. loom_kernel-9.1.0/src/loom/etl/declarative/target/_errors.py +68 -0
  138. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_builder.py +1 -1
  139. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_spec.py +1 -1
  140. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_into.py +37 -3
  141. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_table.py +33 -1
  142. loom_kernel-9.1.0/src/loom/etl/io/_clickhouse_connection.py +44 -0
  143. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_clickhouse.py +20 -21
  144. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/targets/_clickhouse.py +35 -31
  145. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_config.py +4 -3
  146. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/__init__.py +1 -2
  147. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/config_loader.py +2 -1
  148. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/core.py +3 -5
  149. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/_schema.py +11 -5
  150. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/__init__.py +0 -4
  151. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_config.py +63 -69
  152. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/routing.py +3 -2
  153. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_flow_yaml.py +6 -1
  154. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_discovery.py +4 -2
  155. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_factory.py +4 -3
  156. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_slack.py +5 -2
  157. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_sns.py +3 -2
  158. loom_kernel-9.1.0/src/loom/prometheus/db_pool.py +135 -0
  159. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/lifecycle.py +6 -3
  160. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/_body.py +25 -2
  161. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/compiler.py +161 -50
  162. loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_ai.py +524 -0
  163. loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_auth.py +145 -0
  164. loom_kernel-9.1.0/src/loom/rest/fastapi/_auto_sql.py +221 -0
  165. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/_errors.py +30 -3
  166. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/app.py +15 -49
  167. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/auto.py +105 -875
  168. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/openapi.py +8 -18
  169. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/router_runtime.py +53 -44
  170. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/sql.py +12 -25
  171. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/middleware.py +6 -8
  172. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/model.py +8 -5
  173. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/__init__.py +0 -2
  174. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_adapter.py +35 -9
  175. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_resource_manager.py +34 -54
  176. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_runtime_io.py +19 -11
  177. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/_shared.py +6 -17
  178. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/runner.py +6 -5
  179. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_errors.py +6 -17
  180. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_plan.py +20 -17
  181. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/phases/build_plan.py +6 -3
  182. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/phases/validate.py +10 -31
  183. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_config.py +28 -34
  184. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_bytewax_source.py +13 -24
  185. loom_kernel-9.1.0/src/loom/streaming/mongo/_config.py +68 -0
  186. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/__init__.py +0 -2
  187. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_table/__init__.py +3 -4
  188. loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_clickhouse.py +206 -0
  189. loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_delta.py +255 -0
  190. loom_kernel-9.1.0/src/loom/streaming/nodes/_table/_sqlalchemy.py +163 -0
  191. loom_kernel-9.1.0/src/loom/streaming/nodes/_table/common.py +595 -0
  192. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_table/config.py +70 -10
  193. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/repository_harness.py +7 -1
  194. loom_kernel-8.0.1/src/loom/core/cache/keys.py +0 -96
  195. loom_kernel-8.0.1/src/loom/core/config/_boto3.py +0 -22
  196. loom_kernel-8.0.1/src/loom/core/model/struct.py +0 -38
  197. loom_kernel-8.0.1/src/loom/core/persistence/__init__.py +0 -18
  198. loom_kernel-8.0.1/src/loom/core/repository/abc/cursor.py +0 -157
  199. loom_kernel-8.0.1/src/loom/core/repository/abc/session_scope.py +0 -37
  200. loom_kernel-8.0.1/src/loom/etl/declarative/target/_errors.py +0 -30
  201. loom_kernel-8.0.1/src/loom/etl/declarative/target/_schema_mode.py +0 -5
  202. loom_kernel-8.0.1/src/loom/etl/runner/errors.py +0 -7
  203. loom_kernel-8.0.1/src/loom/etl/runner/filtering.py +0 -41
  204. loom_kernel-8.0.1/src/loom/streaming/mongo/_config.py +0 -55
  205. loom_kernel-8.0.1/src/loom/streaming/nodes/_table/common.py +0 -1221
  206. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/.gitignore +0 -0
  207. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/LICENSE +0 -0
  208. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/pyproject.toml +0 -0
  209. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/__init__.py +0 -0
  210. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/__init__.py +0 -0
  211. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_concurrency.py +0 -0
  212. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_filters.py +0 -0
  213. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_paths.py +0 -0
  214. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_roles.py +0 -0
  215. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_startup.py +0 -0
  216. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_transport.py +0 -0
  217. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/_usecase.py +0 -0
  218. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/__init__.py +0 -0
  219. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_binding.py +0 -0
  220. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_handlers.py +0 -0
  221. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/_rpc.py +0 -0
  222. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/a2a/events.py +0 -0
  223. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/abc.py +0 -0
  224. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/bootstrap.py +0 -0
  225. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/__init__.py +0 -0
  226. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_compiler.py +0 -0
  227. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
  228. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
  229. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
  230. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
  231. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
  232. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
  233. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
  234. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
  235. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_output.py +0 -0
  236. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/compiler/phases/_state.py +0 -0
  237. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/__init__.py +0 -0
  238. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_envelope.py +0 -0
  239. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_schema.py +0 -0
  240. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/_v1.py +0 -0
  241. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
  242. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/describe.py +0 -0
  243. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/__init__.py +0 -0
  244. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
  245. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
  246. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
  247. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
  248. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
  249. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
  250. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
  251. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
  252. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
  253. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
  254. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
  255. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
  256. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
  257. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
  258. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
  259. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
  260. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
  261. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
  262. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
  263. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
  264. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
  265. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
  266. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
  267. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/__init__.py +0 -0
  268. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_batch.py +0 -0
  269. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_columns.py +0 -0
  270. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_frames.py +0 -0
  271. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_ledger.py +0 -0
  272. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_runner.py +0 -0
  273. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/etl/_validation.py +0 -0
  274. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/__init__.py +0 -0
  275. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/endpoints.py +0 -0
  276. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/response.py +0 -0
  277. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/fastapi/streaming.py +0 -0
  278. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/pricing.py +0 -0
  279. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/registry.py +0 -0
  280. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/__init__.py +0 -0
  281. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_bounded.py +0 -0
  282. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_chain.py +0 -0
  283. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_conversation.py +0 -0
  284. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_grants.py +0 -0
  285. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_handle.py +0 -0
  286. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_health.py +0 -0
  287. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_hooks.py +0 -0
  288. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_limits.py +0 -0
  289. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/runtime/_mcp.py +0 -0
  290. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/validate/__init__.py +0 -0
  291. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/ai/validate/__main__.py +0 -0
  292. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/__init__.py +0 -0
  293. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/auto.py +0 -0
  294. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/constants.py +0 -0
  295. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/runner.py +0 -0
  296. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/celery/service.py +0 -0
  297. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/__init__.py +0 -0
  298. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/app.py +0 -0
  299. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/cli/schema.py +0 -0
  300. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/async_bridge.py +0 -0
  301. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/__init__.py +0 -0
  302. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_decide.py +0 -0
  303. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_grants.py +0 -0
  304. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_roles.py +0 -0
  305. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/_scope.py +0 -0
  306. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/elevation.py +0 -0
  307. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/authz/product.py +0 -0
  308. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/__init__.py +0 -0
  309. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/core_model.py +0 -0
  310. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/protocol.py +0 -0
  311. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/backend/scoped_ddl.py +0 -0
  312. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/__init__.py +0 -0
  313. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
  314. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/bootstrap/kernel.py +0 -0
  315. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/__init__.py +0 -0
  316. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/_batching.py +0 -0
  317. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/_single_flight.py +0 -0
  318. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/__init__.py +0 -0
  319. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/backend.py +0 -0
  320. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/abc/dependency.py +0 -0
  321. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/calls.py +0 -0
  322. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/codec.py +0 -0
  323. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/dependency.py +0 -0
  324. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/errors.py +0 -0
  325. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/memory.py +0 -0
  326. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/serializer.py +0 -0
  327. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/cache/wiring.py +0 -0
  328. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/__init__.py +0 -0
  329. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/adapter.py +0 -0
  330. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/base.py +0 -0
  331. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/field.py +0 -0
  332. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/command/introspection.py +0 -0
  333. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/compiler.py +0 -0
  334. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/_includes.py +0 -0
  335. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/configurable.py +0 -0
  336. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/context.py +0 -0
  337. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/errors.py +0 -0
  338. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/model.py +0 -0
  339. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/resolver.py +0 -0
  340. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/secrets.py +0 -0
  341. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/config/ssm.py +0 -0
  342. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/contracts/__init__.py +0 -0
  343. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/contracts/manifest.py +0 -0
  344. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/__init__.py +0 -0
  345. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/container.py +0 -0
  346. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/di/scope.py +0 -0
  347. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/__init__.py +0 -0
  348. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/_utils.py +0 -0
  349. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/base.py +0 -0
  350. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/interfaces.py +0 -0
  351. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/manifest.py +0 -0
  352. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/discovery/modules.py +0 -0
  353. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/__init__.py +0 -0
  354. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/compilable.py +0 -0
  355. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/compiler.py +0 -0
  356. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/events.py +0 -0
  357. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/metrics.py +0 -0
  358. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/plan.py +0 -0
  359. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/engine/post_commit.py +0 -0
  360. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/errors/codes.py +0 -0
  361. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/__init__.py +0 -0
  362. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/eval.py +0 -0
  363. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/nodes.py +0 -0
  364. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/expr/refs.py +0 -0
  365. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/__init__.py +0 -0
  366. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/context.py +0 -0
  367. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/identity.py +0 -0
  368. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/issuer.py +0 -0
  369. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/identity/wire.py +0 -0
  370. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/__init__.py +0 -0
  371. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/base.py +0 -0
  372. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/introspection/describe.py +0 -0
  373. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/__init__.py +0 -0
  374. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/callback.py +0 -0
  375. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/context.py +0 -0
  376. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/handle.py +0 -0
  377. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/job.py +0 -0
  378. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/job/service.py +0 -0
  379. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/abc.py +0 -0
  380. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/checks.py +0 -0
  381. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/config.py +0 -0
  382. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/registry.py +0 -0
  383. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/logger/structlogger.py +0 -0
  384. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/_json_schema.py +0 -0
  385. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/base.py +0 -0
  386. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/enums.py +0 -0
  387. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/partition.py +0 -0
  388. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/privilege.py +0 -0
  389. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/projection.py +0 -0
  390. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/relation.py +0 -0
  391. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/model/scoped.py +0 -0
  392. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/__init__.py +0 -0
  393. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/event.py +0 -0
  394. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/__init__.py +0 -0
  395. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/noop.py +0 -0
  396. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/observer/structlog.py +0 -0
  397. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/otel_ids.py +0 -0
  398. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/protocol.py +0 -0
  399. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/runtime.py +0 -0
  400. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/span.py +0 -0
  401. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/observability/topology.py +0 -0
  402. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/persistence/registry.py +0 -0
  403. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/__init__.py +0 -0
  404. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/plugins/optional.py +0 -0
  405. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/__init__.py +0 -0
  406. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/loaders.py +0 -0
  407. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/projection/runtime.py +0 -0
  408. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/__init__.py +0 -0
  409. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/errors.py +0 -0
  410. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/query.py +0 -0
  411. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
  412. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/repo_for.py +0 -0
  413. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/abc/repository.py +0 -0
  414. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
  415. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
  416. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/__init__.py +0 -0
  417. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
  418. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/uow.py +0 -0
  419. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mongo/values.py +0 -0
  420. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/mutation.py +0 -0
  421. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/registration.py +0 -0
  422. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/registry.py +0 -0
  423. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
  424. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
  425. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
  426. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
  427. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
  428. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
  429. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
  430. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
  431. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
  432. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
  433. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
  434. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
  435. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
  436. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
  437. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
  438. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
  439. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
  440. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
  441. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
  442. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
  443. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
  444. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
  445. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
  446. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
  447. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
  448. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
  449. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
  450. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
  451. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
  452. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
  453. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
  454. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/response/__init__.py +0 -0
  455. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/response/base.py +0 -0
  456. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/__init__.py +0 -0
  457. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/ref.py +0 -0
  458. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/routing/resolver.py +0 -0
  459. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/runner.py +0 -0
  460. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema/__init__.py +0 -0
  461. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema/schema_mode.py +0 -0
  462. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/schema_names.py +0 -0
  463. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/__init__.py +0 -0
  464. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/__init__.py +0 -0
  465. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/contracts.py +0 -0
  466. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/abc/errors.py +0 -0
  467. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/caller_bound.py +0 -0
  468. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
  469. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
  470. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/roles.py +0 -0
  471. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/sql/service.py +0 -0
  472. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/symbols.py +0 -0
  473. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/tracing/__init__.py +0 -0
  474. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/tracing/context.py +0 -0
  475. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transaction.py +0 -0
  476. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transport/__init__.py +0 -0
  477. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/transport/adapter.py +0 -0
  478. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/__init__.py +0 -0
  479. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/abc.py +0 -0
  480. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/uow/context.py +0 -0
  481. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/_predicates.py +0 -0
  482. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/agent_markers.py +0 -0
  483. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/constants.py +0 -0
  484. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/factory.py +0 -0
  485. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/field_ref.py +0 -0
  486. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/keys.py +0 -0
  487. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/markers.py +0 -0
  488. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/mcp_markers.py +0 -0
  489. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/outcome.py +0 -0
  490. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/registry.py +0 -0
  491. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/core/use_case/use_case.py +0 -0
  492. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/_uri.py +0 -0
  493. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/__init__.py +0 -0
  494. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_format_registry.py +0 -0
  495. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
  496. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_common.py +0 -0
  497. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_log.py +0 -0
  498. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
  499. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
  500. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
  501. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_path_template.py +0 -0
  502. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_predicate.py +0 -0
  503. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
  504. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
  505. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/__init__.py +0 -0
  506. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
  507. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
  508. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_frame.py +0 -0
  509. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_historify.py +0 -0
  510. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
  511. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
  512. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
  513. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/__init__.py +0 -0
  514. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
  515. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_historify.py +0 -0
  516. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_reader.py +0 -0
  517. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
  518. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
  519. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
  520. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_options.py +0 -0
  521. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_paths.py +0 -0
  522. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/checkpoint/_scope.py +0 -0
  523. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/__init__.py +0 -0
  524. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_binding.py +0 -0
  525. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_plan.py +0 -0
  526. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
  527. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/compiler/_validators_config.py +0 -0
  528. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_format.py +0 -0
  529. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_read_options.py +0 -0
  530. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_utils.py +0 -0
  531. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/_write_options.py +0 -0
  532. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
  533. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_params.py +0 -0
  534. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
  535. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
  536. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
  537. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/__init__.py +0 -0
  538. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from.py +0 -0
  539. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
  540. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
  541. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
  542. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_client.py +0 -0
  543. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_file.py +0 -0
  544. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
  545. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
  546. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
  547. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
  548. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/declarative/target/_temp.py +0 -0
  549. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/__init__.py +0 -0
  550. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_agents.py +0 -0
  551. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_dispatcher.py +0 -0
  552. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/executor/_executor.py +0 -0
  553. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/__init__.py +0 -0
  554. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/_registry.py +0 -0
  555. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/__init__.py +0 -0
  556. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
  557. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
  558. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
  559. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo.py +0 -0
  560. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
  561. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
  562. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
  563. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/sources/_serialization.py +0 -0
  564. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/io/targets/__init__.py +0 -0
  565. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/__init__.py +0 -0
  566. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_observer.py +0 -0
  567. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/_records.py +0 -0
  568. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
  569. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
  570. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
  571. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
  572. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/__init__.py +0 -0
  573. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_builder.py +0 -0
  574. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_ops.py +0 -0
  575. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_protocol.py +0 -0
  576. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_runner.py +0 -0
  577. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/_step.py +0 -0
  578. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
  579. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
  580. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/__init__.py +0 -0
  581. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_generics.py +0 -0
  582. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_params.py +0 -0
  583. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
  584. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_process.py +0 -0
  585. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_sql.py +0 -0
  586. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step.py +0 -0
  587. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step_client.py +0 -0
  588. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
  589. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_agents.py +0 -0
  590. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_providers.py +0 -0
  591. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runner/_wiring.py +0 -0
  592. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/__init__.py +0 -0
  593. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/_config_values.py +0 -0
  594. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/runtime/contracts.py +0 -0
  595. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/__init__.py +0 -0
  596. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/schema/_contract.py +0 -0
  597. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_file_locator.py +0 -0
  598. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/storage/_locator.py +0 -0
  599. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/__init__.py +0 -0
  600. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_result.py +0 -0
  601. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_runners.py +0 -0
  602. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_scenario.py +0 -0
  603. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/_stubs.py +0 -0
  604. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/etl/testing/spark.py +0 -0
  605. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/__init__.py +0 -0
  606. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_async.py +0 -0
  607. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_config.py +0 -0
  608. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_ctx.py +0 -0
  609. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_meta.py +0 -0
  610. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_placeholders.py +0 -0
  611. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/_summary.py +0 -0
  612. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/__init__.py +0 -0
  613. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_schedule.py +0 -0
  614. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
  615. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
  616. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/__init__.py +0 -0
  617. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_assemble.py +0 -0
  618. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_backfill.py +0 -0
  619. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
  620. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_body.py +0 -0
  621. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_common.py +0 -0
  622. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_factory.py +0 -0
  623. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_hooks.py +0 -0
  624. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_maintenance.py +0 -0
  625. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_params.py +0 -0
  626. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_run_name.py +0 -0
  627. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_runtime.py +0 -0
  628. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_signature.py +0 -0
  629. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/flow/_stages.py +0 -0
  630. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/__init__.py +0 -0
  631. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_model.py +0 -0
  632. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_s3.py +0 -0
  633. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/manifest/_store.py +0 -0
  634. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/__init__.py +0 -0
  635. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_event.py +0 -0
  636. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_format.py +0 -0
  637. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/notify/_port.py +0 -0
  638. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/__init__.py +0 -0
  639. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_flow.py +0 -0
  640. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
  641. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_manifest.py +0 -0
  642. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prefect/observer/_task_run.py +0 -0
  643. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/__init__.py +0 -0
  644. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/_instruments.py +0 -0
  645. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/adapter.py +0 -0
  646. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/kafka.py +0 -0
  647. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/prometheus/middleware.py +0 -0
  648. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/py.typed +0 -0
  649. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/__init__.py +0 -0
  650. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/adapter.py +0 -0
  651. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/__init__.py +0 -0
  652. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/abc.py +0 -0
  653. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/config.py +0 -0
  654. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/jwt.py +0 -0
  655. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/auth/middleware.py +0 -0
  656. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/autocrud.py +0 -0
  657. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/checks.py +0 -0
  658. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/config.py +0 -0
  659. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/constants.py +0 -0
  660. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/cors.py +0 -0
  661. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/errors.py +0 -0
  662. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/__init__.py +0 -0
  663. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
  664. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/health.py +0 -0
  665. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/fastapi/response.py +0 -0
  666. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/rest/rest_adapter.py +0 -0
  667. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/__init__.py +0 -0
  668. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
  669. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
  670. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
  671. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_errors.py +0 -0
  672. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_operators.py +0 -0
  673. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
  674. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
  675. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
  676. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
  677. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
  678. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
  679. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
  680. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
  681. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
  682. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/__init__.py +0 -0
  683. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_bindings.py +0 -0
  684. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/compiler/_compiler.py +0 -0
  685. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/__init__.py +0 -0
  686. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_errors.py +0 -0
  687. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_exceptions.py +0 -0
  688. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_message.py +0 -0
  689. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_tracing.py +0 -0
  690. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/core/_typing.py +0 -0
  691. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/graph/__init__.py +0 -0
  692. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/graph/_flow.py +0 -0
  693. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/__init__.py +0 -0
  694. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_codec.py +0 -0
  695. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_errors.py +0 -0
  696. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
  697. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_message.py +0 -0
  698. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_record.py +0 -0
  699. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/_wire.py +0 -0
  700. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
  701. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
  702. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
  703. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
  704. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
  705. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
  706. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
  707. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
  708. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
  709. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/__init__.py +0 -0
  710. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_event.py +0 -0
  711. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/mongo/_normalize.py +0 -0
  712. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_boundary.py +0 -0
  713. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_branches.py +0 -0
  714. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
  715. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
  716. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_decompose.py +0 -0
  717. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
  718. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
  719. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_fork.py +0 -0
  720. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_helpers.py +0 -0
  721. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_mongo.py +0 -0
  722. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_protocols.py +0 -0
  723. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_router.py +0 -0
  724. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_shape.py +0 -0
  725. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_sink.py +0 -0
  726. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_step.py +0 -0
  727. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/_with.py +0 -0
  728. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/nodes/refs.py +0 -0
  729. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/streaming/testing.py +0 -0
  730. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/__init__.py +0 -0
  731. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/agents.py +0 -0
  732. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/golden.py +0 -0
  733. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/http_harness.py +0 -0
  734. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/in_memory.py +0 -0
  735. {loom_kernel-8.0.1 → loom_kernel-9.1.0}/src/loom/testing/runner.py +0 -0
@@ -2,6 +2,35 @@
2
2
 
3
3
  ## ✨ Features
4
4
 
5
+ ### etl
6
+
7
+ - **etl:** `IntoTable(...).upsert(..., delete_flag=...)` deletes matched rows
8
+ whose boolean source column is true and does not insert unmatched rows with
9
+ that flag. A false or null flag keeps the normal update or insert; null is
10
+ read as false (`coalesce(s.<flag>, false)`). The column is removed before
11
+ schema alignment, including `SchemaMode.STRICT`, so it is never written and
12
+ never appears in the update or insert maps. It must exist on the source
13
+ frame, be boolean, must not be a key, a partition column, or listed in
14
+ `exclude` or `include`, and must not name a column of the target table;
15
+ otherwise `UpsertDeleteFlagError` is raised before anything is written. The
16
+ Polars writer applies it. Any other writer, including Spark, raises
17
+ `UnsupportedUpsertDeleteFlagError` and does not write. On first write the
18
+ table is created from the unflagged rows, so a batch where every row is
19
+ flagged creates an empty table. A key repeated in the source batch (for
20
+ example a tombstone and a live row) fails the MERGE. With
21
+ `SchemaMode.EVOLVE` the MERGE does not add new source columns, as before.
22
+ Omitting `delete_flag` leaves the MERGE byte-for-byte as it was: matched
23
+ update and unmatched insert, with no delete clause. `UpsertSpec` gains
24
+ `delete_flag`; `UpsertDeleteFlagError` and
25
+ `UnsupportedUpsertDeleteFlagError` are exported from `loom.etl`.
26
+
27
+ # 🚀 Releases 2.1.3 to 9.0.0
28
+
29
+ Entries from 2.1.3 to 9.0.0 were kept under one heading and are not split
30
+ by version; each release's own list is in its GitHub Release notes.
31
+
32
+ ## ✨ Features
33
+
5
34
  ### core
6
35
 
7
36
  - **core:** range-partitioned row-scoped tables.
@@ -99,6 +128,13 @@
99
128
  parameter raises a `TypeError` naming the code. `AgentErrorCode`,
100
129
  `StreamingErrorCode` and `ETLErrorCode` are such catalogues, and
101
130
  `ETLCompilationError.from_issue(issue)` raises the ETL error for an issue.
131
+ - **core:** `loom.core.logger.log_context(**values)` adds fields to every log
132
+ record emitted inside the block through `get_logger` with its default
133
+ factory, and to plain stdlib records once `configure_logging` has installed
134
+ loom's formatter, so an application can bind, say, an audit `request_id`
135
+ without importing structlog. The values follow the current thread or
136
+ asyncio task, and each key regains its previous value on exit, even by
137
+ exception. The block must be entered and exited in the same context.
102
138
 
103
139
  ### ai
104
140
 
@@ -412,7 +448,7 @@
412
448
  selection can be checked without running it. A bare string as `include`
413
449
  raises `TypeError`. The runner now filters through it. `InvalidStageError`
414
450
  is exported from `loom.etl.compiler` as well; it is the same class as
415
- `loom.etl.runner.InvalidStageError` and `loom.etl.InvalidStageError`.
451
+ `loom.etl.InvalidStageError`.
416
452
  - **etl:** `iter_processes`, `iter_steps_in_process` and `iter_all_steps` are
417
453
  exported from `loom.etl.compiler`. They flatten a compiled plan in
418
454
  execution order, parallel groups in declaration order, so code that walks
@@ -459,6 +495,68 @@
459
495
 
460
496
  ### core
461
497
 
498
+ - **core:** `RuleViolation` and `RuleViolations` are no longer exported by
499
+ `loom.core.use_case` or `loom.core.use_case.rule`. Import them from
500
+ `loom.core.errors`, their only public home.
501
+ - **core:** wrapping a repository in `CachedRepository` raises `RuntimeError`
502
+ when one of its `@cache_query` reads has a missing return annotation, one
503
+ the defining module cannot resolve, or one outside the supported grammar,
504
+ naming the repository and the method; a `@cached` repository therefore fails
505
+ when it is built. Before, wrapping emitted a `DeprecationWarning` and logged
506
+ `CacheQueryReturnTypeUnusable`, and the cached call returned the decoded
507
+ payload instead of the declared type. Annotate the read's return type with a
508
+ struct, a scalar, or a `list`, `tuple` or optional of those. A
509
+ `@cache_query` coroutine that is not defined on the repository class, such
510
+ as one set on the instance, raises `RuntimeError` when it is looked up on
511
+ the wrapper, since no codec was built for it; define it as a method of the
512
+ class.
513
+ - **core:** a field annotated `X | UnsetType` infers `X`'s column type.
514
+ `UNSET` means "not provided", not another type, so `str | UnsetType` now
515
+ compiles to `String` and `int | UnsetType` to `Integer` instead of `JSON`,
516
+ and `Annotated[str, String(20)] | UnsetType` reads its declared type. Such
517
+ a column is scalar: a REST route may declare it filterable, `like` and
518
+ `ilike` included for text, and sortable by offset; a cursor sort on it is
519
+ still refused, since a cursor key must be a bare type. Nullability is
520
+ unchanged: `str | None | UnsetType` admits `None` and is nullable,
521
+ `UnsetType` alone keeps the column `NOT NULL`. An undeclared
522
+ `Decimal | UnsetType`, plain `Enum | UnsetType` or `Literal[...] | UnsetType`
523
+ now needs a declared column type, as it does without `UnsetType`. On Mongo,
524
+ a `str | UnsetType` or `UUID | UnsetType` primary key is now accepted, and
525
+ a range filter or sort on a `Decimal | UnsetType` field is refused, as on a
526
+ `Decimal` field. Alembic autogenerate will show the type change from `JSON`
527
+ for existing tables with such columns.
528
+ - **core:** a column's nullability follows its field's annotation. A field
529
+ whose annotation admits `None` (`x: int | None = None`, also inside
530
+ `Annotated`) compiles to a nullable column; any other field compiles to
531
+ `NOT NULL`, and a primary key column is `NOT NULL` whatever its annotation.
532
+ Before, every column was `NOT NULL` unless declared otherwise, so the model
533
+ accepted `None` and the database refused it on insert. `nullable=` on
534
+ `ColumnField`, `ScopedField` or `Field` now defaults to `None` (follow the
535
+ annotation) and a declared `True` or `False` still wins. Alembic
536
+ autogenerate will propose `nullable` changes for existing tables whose
537
+ Optional fields were created `NOT NULL`; to keep such a column `NOT NULL`,
538
+ declare `nullable=False`. ETL schema contracts keep their own rule (a
539
+ column is nullable unless declared otherwise), which this change does not
540
+ touch.
541
+ - **core:** a `uuid.UUID` field without a declared column type is now a
542
+ `Uuid` column (`loom.core.model.Uuid`, SQLAlchemy `Uuid`) instead of
543
+ `JSON`: `UUID` on Postgres, `CHAR(32)` holding the hex form on dialects
544
+ without a native UUID type, such as SQLite. Such a field is now a scalar
545
+ column, so REST `filterable`, `sortable` and `ALL` accept it on every
546
+ backend, `mongo` included; on SQLite a cursor walk sorted by it pages in
547
+ UUID order and an equality filter on it matches. Streaming `IntoTable` with the
548
+ SQLAlchemy backend binds a `UUID` field the same way instead of failing to
549
+ serialise it as JSON. Migration: an existing table with such a column needs
550
+ a revision changing its type; Alembic autogenerate reports it as a type
551
+ change from `JSON` to `Uuid`. Postgres does not cast `json` to `uuid`, so
552
+ the revision needs `postgresql_using="(<column> #>> '{}')::uuid"`. On a
553
+ dialect without a native UUID type the old rows hold JSON text (the quoted
554
+ UUID with dashes), which the `Uuid` column cannot read, so after the type
555
+ change the revision rewrites each value to its 32-character hex. On
556
+ SQLite: `op.batch_alter_table` for the type change, then
557
+ `UPDATE <table> SET <column> = replace(json_extract(<column>, '$'), '-', '')`.
558
+ Rewriting before the type change loses values on SQLite: a hex form made
559
+ only of digits is stored as a number in the `JSON` column.
462
560
  - **core:** a `Decimal` field, plain or optional, declares its column type: a
463
561
  SQLAlchemy model with an undeclared one is refused when it is compiled,
464
562
  naming the field. loom inferred `NUMERIC(10, 2)`, and Postgres silently
@@ -560,6 +658,81 @@
560
658
  or `RuleViolation` it returns no longer fails the rule. Migrate
561
659
  `Rule.check(F(Order).total, via=lambda v: v <= 0, message="total must be > 0")`
562
660
  to `Rule.check(F(Order).total, via=lambda v: "total must be > 0" if v <= 0 else None)`.
661
+ - **core:** cursor signing keys are required (ADR 0004). An application whose
662
+ persistence backend serves repositories (`sqlalchemy`, `mongo`), and a
663
+ Celery worker that registers repositories, read `persistence.cursors` at
664
+ startup and fail with a `ConfigError` without a key:
665
+
666
+ ```yaml
667
+ persistence:
668
+ cursors:
669
+ current_key_id: "2026-10"
670
+ keys:
671
+ "2026-10": {env: CURSOR_KEY_2026_10} # or {path: /run/secrets/...}
672
+ ```
673
+
674
+ Keys are read from a file or an environment variable, never written in the
675
+ configuration, as standard base64 decoding to at least 32 random bytes
676
+ (`openssl rand -base64 32`); a passphrase is refused. Older key ids stay in
677
+ `keys` to verify the tokens they signed during a rotation.
678
+ The default is `signed` in every environment; `signing: ephemeral` (a
679
+ random per-process key, for `development.yaml`) and `signing: unsigned`
680
+ (for `test.yaml`) are explicit opt-outs, and both log a WARNING at
681
+ startup. In production and staging the deploy check `loom.cursors.E001`
682
+ fails startup, and `loom check --deploy` fails, when a `database` or
683
+ `persistence.mongo` section is set and `signing` is not `signed` or
684
+ `current_key_id` names no entry of `keys`. No `config.overridable` entry
685
+ may open a key under `persistence.cursors`. A key's `env` source must not
686
+ name a `LOOM_*` variable. Tokens issued before this release are refused:
687
+ clients restart from the first page.
688
+ - **core:** a cursor page orders only by non-null columns of a type a token
689
+ carries; a dotted path, a JSON, `bytes` or optional column answers
690
+ `400 unsupported_query` before the query runs (`require_cursor_sort`), and
691
+ a page whose last row holds a non-finite number or a value the token
692
+ cannot carry answers 400 instead of 500. An empty cursor is an invalid
693
+ token on SQLAlchemy as on Mongo. Tokens bind the model as
694
+ `module.qualname`; `UnsupportedQuery` and the client's 400 name it by its
695
+ qualified name alone. `CursorCodec.encode`/`decode`, `require_cursor_sort`
696
+ and `QuerySpecCompiler(model=...)` take the model class (or a name). Mongo
697
+ issues the next token in the model's types, so a page sorted by a date or
698
+ UUID column, or keyed by a UUID, reaches the next page.
699
+ - **core:** one `CursorCodec` per process: the registration modules register
700
+ it with `register_cursor_codec`, which raises `ConfigError` when a
701
+ different codec is already registered, and, in a deployed environment,
702
+ for an `ephemeral` or `unsigned` codec unless `CursorCodec.from_context`
703
+ built it from a configuration silencing `loom.cursors.E001`. Without a
704
+ registered `Environment` the process environment decides (`LOOM_ENV`, else
705
+ production).
706
+ - **core:** `loom.core.checks.silenced_checks(config)` returns the ids
707
+ `checks.silenced` lists, as the deploy-check runner reads them.
708
+ - **core:** the unsigned module functions `encode_cursor` and
709
+ `decode_cursor` are gone. `CursorCodec` (with `CursorConfig` and
710
+ `CursorKeySource`, exported from `loom.core.repository.abc`) issues and
711
+ verifies tokens: `encode(cursor, *, model, query, scope)` and
712
+ `decode(token, *, backend, model, query, scope, columns, primary_key)`,
713
+ where `scope` is required and `""` binds a token to no tenant, `columns`
714
+ maps each column name to its annotation and `primary_key` names the key
715
+ columns in order. A sort key or primary-key value whose type is not its
716
+ column's is refused (`400 unsupported_query`), as is a sort field missing
717
+ from `columns`. The backends
718
+ register the codec they build in DI, so a service paginating by hand
719
+ resolves it with `container.resolve(CursorCodec)`. A decoded datetime key
720
+ is always aware. A `time` sort key is carried too, with the offset it was
721
+ issued with; before, a page sorted by a column holding `time` values
722
+ raised `TypeError` when it issued the next cursor.
723
+ - **core:** `RepositorySQLAlchemy`, `RepositoryMongo`, `QuerySpecCompiler`
724
+ (with a required `scope` and `columns` too), `SQLAlchemyDefaultRepositoryBuilder`,
725
+ `MongoDefaultRepositoryBuilder`, `build_sqlalchemy_repository_registration_module`,
726
+ `build_mongo_repository_registration_module` and
727
+ `loom.testing.build_repository_harness` take a required keyword-only
728
+ `cursor_codec`. A custom repository `builder` passes
729
+ `context.container.resolve(CursorCodec)`. `extract_next_cursor` returns the
730
+ next `Cursor` position instead of a token, and `SessionManager` gains
731
+ `current_settings()`. SQLAlchemy repositories bind cursors to the caller's
732
+ `loom.scope.*` session values. `loom.core.environment` gains
733
+ `configured_variable(name)`, which reads a variable a configuration names
734
+ and refuses a `LOOM_*` name.
735
+
563
736
  - **core:** the `LoomType` protocol gains `from_query(params)`, which
564
737
  validates query-string values strictly. A number takes the JSON number
565
738
  grammar and must be finite, an integer its integer subset within
@@ -577,8 +750,7 @@
577
750
  takes the tuple as its first argument and raises `TypeError` for anything
578
751
  else. A cursor token issued for such a model before this release is refused with
579
752
  `UnsupportedQuery`, `400 unsupported_query`; clients restart from the first
580
- page. `decode_cursor` takes `id_count`, the number of key columns, and
581
- `get_id_attributes` returns every key column name.
753
+ page. `get_id_attributes` returns every key column name.
582
754
 
583
755
  - **core:** `compile_all` raises `ValueError` for a model with a composite
584
756
  primary key that declares a relation or a projection whose loader runs
@@ -673,6 +845,8 @@
673
845
  present convert those rows deliberately (for example to UTC with
674
846
  `(c::timetz AT TIME ZONE 'UTC')::time`) before changing the type. MongoDB is
675
847
  unaffected: it stores `date` and `time` values as ISO 8601 strings.
848
+ - **core:** `to_column_value` is imported from `loom.core.model.convert`; it is
849
+ no longer exported by `loom.core.repository.sqlalchemy.values`.
676
850
 
677
851
  ### ai
678
852
 
@@ -681,9 +855,15 @@
681
855
  example `spec_malformed`, `engine_not_found` and `mcp_server_unreachable`.
682
856
  Build an issue with `AgentErrorCode.X.issue(...)` and keyword arguments,
683
857
  such as `AgentErrorCode.ENGINE_NOT_FOUND.issue(component="openai-agents",
684
- available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too:
685
- `AgentCompilationError` still turns a bare string into an `UNSPECIFIED`
686
- issue. Messages keep their text; a list that is empty renders `none`.
858
+ available=["pydantic-ai"])`. `loom.ai.errors.from_message` is removed too.
859
+ Messages keep their text; a list that is empty renders `none`.
860
+ - **ai:** `AgentCompilationError` takes `AgentCompilationIssue` values only;
861
+ bare strings and the `AgentErrorCode.UNSPECIFIED` code they became are
862
+ removed. Build an issue from an `AgentErrorCode` member with `.issue()`.
863
+ The five pydantic-ai engine failures that raised bare strings now carry
864
+ their own codes, with the same messages: `TOOL_NAME_COLLISION`,
865
+ `TOOL_NAME_TOO_LONG`, `USECASE_NOT_COMPILED`, `CAPABILITY_KIND_NO_BUILDER`
866
+ and `MCP_CONNECTION_NOT_OPENED`.
687
867
  - **ai:** `AgentCompilationIssue` is a type alias of
688
868
  `CompileIssue[AgentErrorCode]` from `loom.core.errors.codes`, not a class.
689
869
  It has the same fields, but `isinstance` against it raises `TypeError`
@@ -762,6 +942,9 @@
762
942
  declares both a pydantic `type_ref` output and `output_check` serialises
763
943
  an accepted answer twice per attempt — once for the check's own builtins
764
944
  projection, once for the wire — accepted rather than optimised away.
945
+ - **ai:** a provider's `credentials_ref` is read through
946
+ `loom.core.environment.configured_variable` and may not name a `LOOM_*`
947
+ variable.
765
948
 
766
949
  ### rest
767
950
 
@@ -818,12 +1001,56 @@
818
1001
  - **rest:** a JSON object body that fails `Command` validation now answers
819
1002
  `422 boundary_validation` with a `violations` list (`{field, message}`
820
1003
  pairs, `field` being the wire name the client sent, the same shape
821
- `rule_violations` already uses) instead of a generic `500`; malformed
822
- JSON and a non-object body are unchanged. `Command.from_payload` now
823
- raises `BoundaryValidationError` — a `ValueError` — instead of
824
- `msgspec.ValidationError`. The root `title` is dropped on pydantic
825
- OpenAPI schemas for request bodies and responses alike, matching the
826
- untitled document a Struct always produced.
1004
+ `rule_violations` already uses) instead of a generic `500`.
1005
+ `Command.from_payload` now raises `BoundaryValidationError` — a
1006
+ `ValueError` — instead of `msgspec.ValidationError`. The root `title` is
1007
+ dropped on pydantic OpenAPI schemas for request bodies and responses alike,
1008
+ matching the untitled document a Struct always produced.
1009
+ - **rest:** a `sortable` column must be a field of the items the route
1010
+ answers with (`PageResult[T]`, `CursorResult[T]` or `list[T]`); a column
1011
+ the response does not show, or a result type that does not say, fails
1012
+ compilation naming the route and the field, since ordering by it reveals
1013
+ its values. `sortable=ALL` opens every scalar column, hidden ones included,
1014
+ and its startup warning says so. `filterable` follows the same rule, with
1015
+ `filterable=ALL` as its escape hatch. "Shown" is decided by field name; a
1016
+ pydantic field declared `exclude=True` is not shown.
1017
+ - **rest:** breaking: a `QuerySpec` route that can serve cursor pages (cursor
1018
+ mode, or the default `allow_pagination_override=True`) must answer with
1019
+ items that show its primary key, which every cursor token carries. A route
1020
+ whose response hides the key, or whose result type is untyped (`str`,
1021
+ `dict[str, Any]`, ...), now fails compilation naming the route and the key.
1022
+ `sortable=ALL` opens it with a warning; a route that must hide its keys
1023
+ serves offset pages only (`pagination_mode` offset and
1024
+ `allow_pagination_override=False`). On such a route the key must also be of
1025
+ a type a token carries, in a scalar column: a key declared in a JSON or
1026
+ array column, which a SQL keyset cannot order, fails compilation instead
1027
+ of on the first cursor request. A bare `UUID` key, a scalar `Uuid` column,
1028
+ compiles and pages on SQLAlchemy and Mongo alike.
1029
+ - **rest:** `create_fastapi_app(interfaces=...)` is removed and `routes` is
1030
+ required; use `create_fastapi_app(result, RouteSources(python=[...]))`.
1031
+ - **rest:** the `QUERY_PARAM_PAGE`, `QUERY_PARAM_LIMIT`,
1032
+ `QUERY_PARAM_PAGINATION`, `QUERY_PARAM_AFTER`, `QUERY_PARAM_CURSOR`,
1033
+ `QUERY_PARAM_SORT`, `QUERY_PARAM_DIRECTION` and `QUERY_PARAM_PROFILE`
1034
+ re-exports of `loom.rest.fastapi.openapi` are removed; use the matching
1035
+ `loom.rest.constants.QueryParam` member (`QueryParam.PAGE`, ...).
1036
+ - **rest:** a request body that is not well-formed JSON — a syntax error,
1037
+ bytes that are not UTF-8, nesting too deep to decode, or an empty body on a
1038
+ route that takes input — now answers `400` with the standard error body
1039
+ (`code: bad_request`, the fixed message `Request body is not valid JSON`,
1040
+ `trace_id`) instead of a generic `500 internal_error` without the `detail`
1041
+ envelope. Well-formed JSON that is not an object (an array, a string, a
1042
+ number, `null`) answers `422 boundary_validation` with the fixed message
1043
+ `Request body must be a JSON object` and one `body` violation, instead of
1044
+ that same `500`. Neither echoes the body. A JSON object that fails
1045
+ validation still answers `422` as before, and the `Content-Type` header is
1046
+ still not checked.
1047
+ - **rest:** the SQL endpoint answers a body that is not well-formed JSON the
1048
+ same way: `400` with `code: bad_request` and the fixed message
1049
+ `Request body is not valid JSON`, instead of a `422 rule_violation` that
1050
+ carried the decoder's message. Bytes that are not UTF-8 inside a JSON
1051
+ string and nesting too deep to decode, which answered a generic
1052
+ `500 internal_error`, are now that `400` too. A well-formed body
1053
+ that does not fit the schema still answers `422 rule_violation`.
827
1054
 
828
1055
  ### prefect
829
1056
 
@@ -914,11 +1141,8 @@
914
1141
  - **etl:** a `WithAgent` compiled by a runner whose config has no `ai:`
915
1142
  section fails with the new code `AGENT_RUNNER_NOT_CONFIGURED` instead of
916
1143
  `AGENT_NOT_FOUND`, which now means only that no artifact declares the name.
917
- - **etl:** the names of `loom.etl.runner.filtering` (`_filter_plan`,
918
- `_filter_process`, `_collect_all_names`, `_map_pipeline_nodes`,
919
- `_map_process_nodes`) are deprecated and removed in loom 3.0; each emits a
920
- `DeprecationWarning` naming its replacement, `loom.etl.compiler.filter_plan`
921
- or, for `_collect_all_names`, `iter_processes` and `iter_all_steps`.
1144
+ - **etl:** `loom.etl.runner.filtering` is removed; use
1145
+ `loom.etl.compiler.filter_plan`.
922
1146
  - **etl:** the Polars writer refuses, under `SchemaMode.STRICT` and
923
1147
  `EVOLVE`, a frame column that is a `Struct` or `List` where the Delta table
924
1148
  has `String`, or `String` where the table has a `Struct` or `List`, at any
@@ -937,8 +1161,7 @@
937
1161
  `Unknown step or process names: [...]` instead of `No steps or processes
938
1162
  match include=[...]`, the constructor's parameter is `unknown`, and the
939
1163
  names are kept on the new `unknown` attribute. Positional construction is
940
- unchanged; `InvalidStageError(include=...)` still works, emits a
941
- `DeprecationWarning` and is removed in loom 3.0. The error survives pickle
1164
+ unchanged. The error survives pickle
942
1165
  with its `unknown` names, so it crosses process boundaries intact.
943
1166
  - **etl:** `ThreadDispatcher` runs each task in a copy of the caller's
944
1167
  context, as `asyncio.to_thread` does, so a step of a parallel group sees
@@ -949,16 +1172,75 @@
949
1172
  caller's context among the requirements on an implementation.
950
1173
  - **etl:** `WithAgent(max_usd=...)` keeps the budget as a `Decimal`. An
951
1174
  `int`, or another `numbers.Integral` such as `numpy.int64`, is converted
952
- exactly. A `float` emits a `DeprecationWarning`, is converted through its
953
- `str()` (`0.1` becomes `Decimal("0.1")`) and is removed in loom 3.0. A
954
- `bool`, accepted before, and any other type, such as `str`, raise
955
- `TypeError`. `NaN`, `sNaN` and `Infinity`, as a `Decimal` or a `float`,
956
- raise `ValueError`, like zero and a negative amount; a `Decimal` `NaN` or
957
- `sNaN` used to raise `decimal.InvalidOperation`, and a `Decimal`
958
- `Infinity`, a `float` `inf` and a `float` `nan` were accepted.
1175
+ exactly. A `bool`, accepted before, and any other type, such as `str`,
1176
+ raise `TypeError`. `NaN`, `sNaN` and `Infinity` raise `ValueError`, like
1177
+ zero and a negative amount; a `Decimal` `NaN` or `sNaN` used to raise
1178
+ `decimal.InvalidOperation`, and a `Decimal` `Infinity` was accepted.
1179
+ - **etl:** `InvalidStageError(include=...)` is removed; use
1180
+ `InvalidStageError(unknown=...)` or pass the names positionally.
1181
+ - **etl:** `WithAgent(max_usd=<float>)` is removed and raises `TypeError`;
1182
+ pass a `Decimal`, such as `Decimal("2.50")`, or an `int`.
1183
+ - **etl:** `loom.etl.CheckpointCleaner` and
1184
+ `loom.etl.checkpoint.CheckpointCleaner` are removed; use
1185
+ `FsspecTempCleaner`, now exported from `loom.etl` as well.
1186
+ - **etl:** the module `loom.etl.declarative.target._schema_mode` is removed;
1187
+ import `SchemaMode` from `loom.core.schema` (or `loom.etl`).
1188
+ - **etl:** `FromClickHouse.select(columns)` is removed; use
1189
+ `FromClickHouse.columns(*columns)`.
1190
+ - **etl:** `ClickHouseSourceSpec.table` is removed; use
1191
+ `ClickHouseSourceSpec.table_ref.ref`.
1192
+ - **etl:** `loom.etl.backends.polars._reader._apply_source_schema` is
1193
+ removed. It was a test helper and has no public replacement.
1194
+ - **etl:** the module `loom.etl.runner.errors` is removed, and neither
1195
+ `loom.etl.runner` nor `loom.etl.runner.core` exports `InvalidStageError`;
1196
+ import it from `loom.etl.compiler` (or `loom.etl`).
1197
+ - **etl:** `loom.etl.io.sources._clickhouse` no longer re-exports
1198
+ `FromClickHouse` and `ClickHouseSourceSpec`; import them from
1199
+ `loom.etl.declarative.source` (`FromClickHouse` also from `loom.etl`).
959
1200
 
960
1201
  ### streaming
961
1202
 
1203
+ - **streaming:** `ConsumerSettings.delivery` is required. A Kafka consumer
1204
+ config without `delivery` fails to decode, so compiling a flow that reads
1205
+ from Kafka raises `CompilationError` with `KAFKA_CONFIG_INVALID` naming the
1206
+ missing field. Before, a missing `delivery` resolved to `at_most_once`.
1207
+ Declare `delivery: at_most_once` to keep that behaviour, or
1208
+ `delivery: at_least_once`. `ConsumerSettings.effective_delivery()` is
1209
+ removed; read `ConsumerSettings.delivery`.
1210
+ - **streaming:** `ConsumerSettings.enable_auto_commit` is removed, together
1211
+ with the `DELIVERY_CONFLICT` compile code. The consumer settings forbid
1212
+ unknown fields, so a config that sets `enable_auto_commit` fails to decode
1213
+ (`KAFKA_CONFIG_INVALID`). Declare `delivery` instead: `enable_auto_commit:
1214
+ false` was `delivery: at_least_once`, and `true` was `delivery:
1215
+ at_most_once`.
1216
+ - **streaming:** `ConsumerSettings.poll_timeout_ms` is removed. The
1217
+ partitioned source ignored it and logged a deprecation warning; a config
1218
+ that sets it now fails to decode (`KAFKA_CONFIG_INVALID`). Remove the key;
1219
+ the partitioned source is tuned with `batch_size` and `poll_backoff_ms`.
1220
+ - **streaming:** `CompilationError` takes `CompilationIssue` values only;
1221
+ bare strings and the `StreamingErrorCode.UNSPECIFIED` code they became are
1222
+ removed. Build an issue from a `StreamingErrorCode` member with `.issue()`.
1223
+ - **streaming:** `CompilationError.errors` is removed. Read the messages from
1224
+ `CompilationError.issues` (`[issue.message for issue in error.issues]`).
1225
+ - **streaming:** an `IntoTable` sink section (`streaming.sinks.<name>`) with a
1226
+ key its backend does not read fails at compile with `SINK_CONFIG_INVALID`,
1227
+ naming every unknown key; on Delta this covers the keys under `staging`
1228
+ too, and a `staging` or `writer_properties` that is not a mapping is
1229
+ refused. Before, such a key was ignored. A SQLAlchemy sink that references a
1230
+ shared `database` reads no pool keys (`pool_size`, `echo`, ...) from its own
1231
+ section, so they are refused there; set them under `database.<name>`.
1232
+ A SQLAlchemy or ClickHouse sink section that sets both `url` and `database`
1233
+ is refused too, instead of one silently winning: a SQLAlchemy sink sets one
1234
+ or the other, and a ClickHouse sink takes its url from `database.<name>`, so
1235
+ it sets `database` only.
1236
+ Delta's `part_max_records` is removed and therefore refused: it was an alias
1237
+ of `writer_properties.max_row_group_size`, which is the key to set. Without
1238
+ `writer_properties` the row groups still hold at most 10 000 rows.
1239
+ `DeltaSinkConfig` has no `part_max_records` attribute.
1240
+ - **streaming:** `CompiledSingleSource` and `CompiledMultiSource` take a
1241
+ required `settings_key`, the config key their consumer settings were
1242
+ resolved from (`kafka.consumer` or `kafka.consumers.<ref>`);
1243
+ `KafkaSettings.consumer_key_for(ref)` names it.
962
1244
  - **streaming:** `FromTopic`, `FromMultiTypeTopic`, `FromMongoCDC` and
963
1245
  `IntoTopic` take no `shape`, `CompiledSingleSource`, `CompiledMultiSource`
964
1246
  and `CompiledMongoCDCSource` have no `shape` field, and `StreamShape.MANY`
@@ -1088,11 +1370,71 @@
1088
1370
  - **streaming:** a sync `With(process=...)` hands on one message at a time, as
1089
1371
  `WithAsync` does. After a `CollectBatch` it handed on whole batches, so as
1090
1372
  the last node of a flow without `output` its messages never completed.
1373
+ - **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds each column with
1374
+ the type core compiles for the field instead of its own map:
1375
+ - a `StrEnum` or `IntEnum` field is written as its scalar (`String`,
1376
+ `Integer`) instead of as JSON;
1377
+ - a column type declared with `ColumnField` (on a `BaseModel`) or
1378
+ `Annotated[T, <ColumnType>]` is used;
1379
+ - a `Decimal`, plain `Enum` or `Literal` field without a declared column
1380
+ type is refused when the partition is built, with core's message, instead
1381
+ of being written as `Numeric()` (a `Decimal`) or as JSON. Declare it, e.g.
1382
+ `Annotated[Decimal, Numeric(precision=12, scale=2)]`, or
1383
+ `Annotated[Decimal, Numeric()]` for an unbounded `NUMERIC`.
1384
+ - **streaming:** `IntoTable` with `Backend.CLICKHOUSE` hands a `date` field to
1385
+ clickhouse-connect as a `date`, as core keeps it for a column, instead of as
1386
+ its ISO-8601 text. clickhouse-connect writes a `Date` column only from a
1387
+ `date` and refused the text ("unsupported operand type(s) for -: 'str' and
1388
+ 'datetime.date'"); a `String` column now refuses the `date` ("object of type
1389
+ 'datetime.date' has no len()"). A `dict` value is written as compact JSON
1390
+ text from `msgspec.json`, keys still sorted (`{"a":1}`, was `{"a": 1}`).
1091
1391
 
1092
1392
  ## 🐛 Fixes
1093
1393
 
1094
1394
  ### core
1095
1395
 
1396
+ - **core:** `RepositoryDynamoDB` reads, updates and deletes by a `UUID`
1397
+ primary key. `get_by_id`, `get_by`, `exists_by`, `update` and `delete`
1398
+ handed the raw key to boto3's `TypeSerializer`, which raised
1399
+ `TypeError: Unsupported type "<class 'uuid.UUID'>"`; `create` already stored
1400
+ the key as a string through `msgspec.to_builtins`. The key is now encoded
1401
+ with that same conversion, so it matches its stored form and round-trips.
1402
+ `update` keeps the key as stored instead of rewriting it from the argument.
1403
+ Attribute values are encoded as before.
1404
+ - **cache:** security: the repository cache keeps each caller's entries apart.
1405
+ The entity key (`get_by_id`, and the rows behind a cached page), the
1406
+ `list_paginated` index key, the `list_with_query` key and the key of a
1407
+ `@cache_query` read (`scope="entity"` and `scope="list"`) now carry the
1408
+ caller's cache scope, so a row, a page of ids, a first page with its next
1409
+ cursor or a custom read's result cached for one caller is no longer served
1410
+ to another that row-level security hides it from. The scope comes from the
1411
+ new, provisional `SupportsCacheScope.cache_scope()` (`""` for a repository
1412
+ without it): `RepositorySQLAlchemy` builds it from every setting the
1413
+ session-settings provider returns, so a policy reading a product setting
1414
+ such as `app.tenant_id` is kept apart too, while cursor tokens stay bound to
1415
+ the `loom.scope.*` settings only. Inside a caller-owned transaction (the
1416
+ unit of work a use case runs in, or a `@transactional` scope) every cached
1417
+ read goes straight to the repository, with no lookup and no store, and so
1418
+ does a call to a `@cache_query` method whose `session` parameter, passed by
1419
+ position or by name, is not `None`. This holds where the backend reports
1420
+ such a transaction, SQLAlchemy and Mongo with transactions; DynamoDB and
1421
+ Mongo with `transactions: false` keep caching, and a read-only use case run
1422
+ outside another unit of work opens none and keeps using the cache. Writes
1423
+ still evict every scope's entries: the scope is not part of the dependency
1424
+ tags, and a write bumps the same generation counters whatever its scope. The
1425
+ scope is read once per cache operation and read again before its writes,
1426
+ which are skipped if it changed. `CachedRepository` implements
1427
+ `cache_scope()` and `has_caller_scoped_session()` by forwarding the wrapped
1428
+ repository's, so a wrapper around it keys by the same scope and stays out of
1429
+ the same transactions, and refuses at construction, with a `RuntimeError`, a
1430
+ repository whose `session_manager` has session settings but which does not
1431
+ implement `cache_scope()`. The list filter, query and `@cache_query`
1432
+ arguments fingerprints in cache keys are now the full SHA-256 instead of its
1433
+ first 64 bits. `entity_key` and `list_index_key` take a required
1434
+ keyword-only `scope`, and the new `query_index_key` and `custom_query_key`
1435
+ build the `list_with_query` and `@cache_query` keys. Existing entity, list,
1436
+ query and `@cache_query` entries are no longer read after the upgrade and
1437
+ expire by their TTL.
1096
1438
  - **core:** one environment selector and deploy checks (ADR 0005). loom had
1097
1439
  two unconnected notions of environment (the logger's `dev`/`prod`, where an
1098
1440
  unknown value meant `dev`, and `FlowCtx.environment`) and nothing checked a
@@ -1143,10 +1485,25 @@
1143
1485
  startup. `parse_environment` validates a value naming an environment.
1144
1486
  - **core:** the SQLAlchemy query compiler converts a filter value, and each
1145
1487
  `in` item, as the repository converts a value it writes
1146
- (`loom.core.repository.sqlalchemy.values.to_column_value`, now shared by
1488
+ (`loom.core.model.convert.to_column_value`, now shared by
1147
1489
  both): an `Enum` member is bound as its value, a JSON column's value is
1148
1490
  reduced to builtins. A plain `Enum` member as the value of a filter on a
1149
1491
  string column failed to bind.
1492
+ - **core:** pagination cursors are signed and decoded strictly (ADR 0004).
1493
+ A cursor token was base64url JSON with no integrity, and a datetime key
1494
+ decoded without a time zone, so a client could forge a position and a
1495
+ consumer comparing it with aware datetimes raised `TypeError` (a 500). A
1496
+ token is now `base64url(payload).base64url(tag)`, the tag an HMAC-SHA256
1497
+ over a domain-separated input bound to the model, the normalised filters,
1498
+ the sort and the caller's scope, verified with `hmac.compare_digest` before
1499
+ the payload is parsed. A malformed, unsigned, forged or rebound token, a
1500
+ key signed by an unknown key id, a datetime key without a time zone, a key
1501
+ of an unknown type, the wrong number of keys or the wrong backend is
1502
+ `UnsupportedQuery` (`400 unsupported_query`), and the message never echoes
1503
+ the token. A naive datetime key, such as a `DateTime(tz=False)` column, is
1504
+ issued as UTC with an explicit offset and compared as naive UTC against
1505
+ that column, on SQLite and Postgres alike.
1506
+
1150
1507
  - **core:** a `BoundaryValidationError` no longer echoes the rejected value
1151
1508
  (#347). msgspec's `Invalid enum value 'x'` (an `Enum`, `IntEnum` or `Literal`
1152
1509
  field or dict key) and `Invalid value 'x'` (a tagged-union tag) become
@@ -1175,8 +1532,9 @@
1175
1532
  column only. The cursor now orders and compares on
1176
1533
  every key column after the sort keys and carries every key value in the
1177
1534
  token; offset pages and `list_paginated` order by every key column too.
1178
- Tokens of single-column keys are unchanged. A cached repository over such a
1179
- model keyed its entries by the first key column too, so a warm
1535
+ That fix leaves tokens of single-column keys as they were. A cached
1536
+ repository over such a model keyed its entries by the first key column
1537
+ too, so a warm
1180
1538
  `list_paginated` or first cursor page served the rows sharing a first key
1181
1539
  value as copies of one of them; it now caches and reloads every row by its
1182
1540
  full key, one `get_by_id` per missing row.
@@ -1212,6 +1570,12 @@
1212
1570
 
1213
1571
  ### etl
1214
1572
 
1573
+ - **etl:** the error for a missing destination table names only advice that
1574
+ works under the policy in force. Under `missing_table_policy='error'` it
1575
+ used to suggest `SchemaMode.OVERWRITE`, which that policy ignores; it now
1576
+ suggests `missing_table_policy='create'`, `'schema_mode'` with
1577
+ `SchemaMode.OVERWRITE`, or creating the table first.
1578
+
1215
1579
  - **etl:** `replace(allow_empty=False)` on Spark writes the rows it checked.
1216
1580
  The writer ran `DataFrame.isEmpty()` and then let the write compute the
1217
1581
  frame again, so a source that changed in between, or a nondeterministic
@@ -1392,6 +1756,11 @@
1392
1756
 
1393
1757
  ### streaming
1394
1758
 
1759
+ - **streaming:** `SINK_CANNOT_TRACK_COMMITS` and
1760
+ `INLINE_SINK_CANNOT_SKIP_COMMITS` point their `field` at the `delivery` of
1761
+ the consumer the source was bound through, `kafka.consumer.delivery` or
1762
+ `kafka.consumers.<ref>.delivery`, instead of `streaming.delivery`, which no
1763
+ config reads.
1395
1764
  - **streaming:** `ForEach` accepts the batch a `BatchStep` produces, so
1396
1765
  `CollectBatch → BatchStep → ForEach → IntoTopic` compiles; it failed with
1397
1766
  `shape mismatch: expected many but got batch before ForEach`. Under
@@ -1482,6 +1851,49 @@
1482
1851
  offset at the step, also when the batch holds several messages of one
1483
1852
  offset that an earlier expanding node produced. The new return type is under
1484
1853
  Behaviour changes.
1854
+ - **streaming:** `IntoTable` with `Backend.SQLALCHEMY` binds a `bytes` field as
1855
+ `LargeBinary` (`bytea` on Postgres). It bound it as text, which Postgres
1856
+ refused for a `bytea` column ("column is of type bytea but expression is of
1857
+ type character varying"). IntoTable now takes each column's type from core's
1858
+ model introspection (`loom.core.backend.sqlalchemy.sa_table_for`), the type
1859
+ a compiled model declares, and builds each row with core's new
1860
+ `loom.core.repository.sqlalchemy.values.to_column_row`, which converts and
1861
+ checks values as the repository does when it writes them: a plain `Enum` as
1862
+ its value, a struct in a JSON column as a dict, an `UNSET` value left out so
1863
+ the column's database default applies, also when other rows of the batch
1864
+ set it, and a `time` whose UTC offset its column cannot take refused with
1865
+ `BoundaryValidationError` (`boundary_validation`) instead of being written
1866
+ without the offset. Relation and projection fields are no longer columns
1867
+ for any backend: the SQLAlchemy and Delta rows included them and failed on
1868
+ their `UNSET` value, and the ClickHouse insert named them. A `date` or
1869
+ `time` field is bound as `Date` or `Time`, as core infers it, so it is
1870
+ written into a Postgres `date` or `time` column; it was bound as `String`
1871
+ and Postgres refused it ("column is of type date but expression is of type
1872
+ character varying").
1873
+ - **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
1874
+ refuses an `UNSET` column value when the item is written, with
1875
+ `BoundaryValidationError` (`boundary_validation`) naming the field and the
1876
+ table. Delta failed later, at a mini-batch or flush, with pyarrow's
1877
+ `ArrowInvalid`, and ClickHouse passed the `UNSET` object to
1878
+ clickhouse-connect's `insert`. Neither can leave a column out for one row as
1879
+ `Backend.SQLALCHEMY` does.
1880
+ - **streaming:** `IntoTable` with `Backend.DELTA` or `Backend.CLICKHOUSE`
1881
+ converts each column value as `Backend.SQLALCHEMY` and core's repository
1882
+ do, with `loom.core.model.convert.to_column_value`: a plain `Enum` becomes
1883
+ its value and a nested `msgspec.Struct` or `LoomStruct` a dict, also inside a
1884
+ list or a dict, while `bytes`, `datetime`, `date`, `time`, `Decimal` and
1885
+ `UUID` are kept. Delta refused an `Enum` or a struct with pyarrow's
1886
+ `ArrowInvalid` ("did not recognize Python value type when inferring an
1887
+ Arrow data type"); a nested struct is now a Delta struct column, as a `dict`
1888
+ field already was, and keeps its `datetime` and `Decimal` types.
1889
+ clickhouse-connect refused an `Enum` or a struct ("object of type ... has no
1890
+ len()") and `json.dumps` a `dict` holding a `Decimal` or `datetime` ("Object
1891
+ of type Decimal is not JSON serializable"); an `Enum` is now inserted as its
1892
+ value and a struct or `dict` as JSON text from `msgspec.json`, a `datetime`
1893
+ inside it as ISO-8601 text and a `Decimal` as decimal text.
1894
+ `to_column_value` moved to `loom.core.model.convert` (under Behaviour
1895
+ changes), so the Delta and ClickHouse writers use it without SQLAlchemy
1896
+ installed.
1485
1897
 
1486
1898
  ### prefect
1487
1899
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: loom-kernel
3
- Version: 8.0.1
3
+ Version: 9.1.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
 
@@ -333,6 +333,10 @@ app:
333
333
  title: My Store API
334
334
  version: 0.1.0
335
335
 
336
+ persistence:
337
+ cursors:
338
+ signing: ephemeral # development.yaml only; production.yaml configures keys
339
+
336
340
  database:
337
341
  url: ${oc.env:DATABASE_URL,sqlite+aiosqlite:///store.db}
338
342
 
@@ -136,7 +136,7 @@ def build_agent_card(
136
136
  "protocolVersion": PROTOCOL_VERSION,
137
137
  "name": plan.name,
138
138
  "description": plan.description,
139
- "url": agent_url(config.base_url, plan.name, prefix=prefix),
139
+ "url": agent_url(config.base_url.reveal(), plan.name, prefix=prefix),
140
140
  "version": str(plan.spec_version),
141
141
  "capabilities": dict(_TRANSPORT_CAPABILITIES),
142
142
  "defaultInputModes": list(_INPUT_MODES),