loom-kernel 6.0.2__tar.gz → 8.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (696) hide show
  1. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/CHANGELOG.md +66 -0
  2. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/PKG-INFO +1 -1
  3. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/backend/sqlalchemy.py +4 -0
  4. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/__init__.py +4 -0
  5. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/_loom_type.py +3 -1
  6. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/introspection.py +4 -2
  7. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/types.py +2 -0
  8. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/backend.py +27 -1
  9. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/mixins.py +29 -7
  10. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +13 -6
  11. loom_kernel-8.0.0/src/loom/core/repository/sqlalchemy/values.py +130 -0
  12. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/_shared.py +22 -22
  13. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/steps.py +39 -6
  14. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_step.py +12 -3
  15. loom_kernel-6.0.2/src/loom/core/repository/sqlalchemy/values.py +0 -51
  16. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/.gitignore +0 -0
  17. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/LICENSE +0 -0
  18. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/README.md +0 -0
  19. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/pyproject.toml +0 -0
  20. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/__init__.py +0 -0
  21. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/__init__.py +0 -0
  22. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_concurrency.py +0 -0
  23. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_filters.py +0 -0
  24. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_paths.py +0 -0
  25. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_roles.py +0 -0
  26. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_startup.py +0 -0
  27. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_transport.py +0 -0
  28. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/_usecase.py +0 -0
  29. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/__init__.py +0 -0
  30. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/_binding.py +0 -0
  31. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/_handlers.py +0 -0
  32. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/_rpc.py +0 -0
  33. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/card.py +0 -0
  34. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/events.py +0 -0
  35. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/a2a/server.py +0 -0
  36. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/abc.py +0 -0
  37. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/bootstrap.py +0 -0
  38. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/__init__.py +0 -0
  39. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/_compiler.py +0 -0
  40. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/_fingerprint.py +0 -0
  41. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/_plan.py +0 -0
  42. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/__init__.py +0 -0
  43. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_capabilities.py +0 -0
  44. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_conversation.py +0 -0
  45. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_feedable.py +0 -0
  46. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_hook.py +0 -0
  47. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_instructions.py +0 -0
  48. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_limits.py +0 -0
  49. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_model_role.py +0 -0
  50. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_output.py +0 -0
  51. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/compiler/phases/_state.py +0 -0
  52. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/config.py +0 -0
  53. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/declarative/__init__.py +0 -0
  54. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/declarative/_envelope.py +0 -0
  55. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/declarative/_schema.py +0 -0
  56. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/declarative/_v1.py +0 -0
  57. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/declarative/schemas/agent-spec-v1.schema.json +0 -0
  58. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/describe.py +0 -0
  59. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/__init__.py +0 -0
  60. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/__init__.py +0 -0
  61. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_a2a.py +0 -0
  62. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_capabilities.py +0 -0
  63. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_engine.py +0 -0
  64. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_errors.py +0 -0
  65. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_escape.py +0 -0
  66. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_events.py +0 -0
  67. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_guards.py +0 -0
  68. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_history.py +0 -0
  69. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_instructions.py +0 -0
  70. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_limits.py +0 -0
  71. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_mcp.py +0 -0
  72. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_models.py +0 -0
  73. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_native.py +0 -0
  74. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_output.py +0 -0
  75. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_returns.py +0 -0
  76. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_schemas.py +0 -0
  77. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/_spec.py +0 -0
  78. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/extras/__init__.py +0 -0
  79. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/extras/a2a.py +0 -0
  80. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/extras/handlebars.py +0 -0
  81. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/extras/mcp.py +0 -0
  82. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/extras/skills.py +0 -0
  83. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/provider.py +0 -0
  84. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/__init__.py +0 -0
  85. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/_shared.py +0 -0
  86. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/anthropic.py +0 -0
  87. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/bedrock.py +0 -0
  88. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/gateway.py +0 -0
  89. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/openai.py +0 -0
  90. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/engines/pydantic_ai/providers/typesafe.py +0 -0
  91. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/errors.py +0 -0
  92. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/__init__.py +0 -0
  93. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_batch.py +0 -0
  94. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_columns.py +0 -0
  95. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_frames.py +0 -0
  96. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_ledger.py +0 -0
  97. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_runner.py +0 -0
  98. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/etl/_validation.py +0 -0
  99. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/fastapi/__init__.py +0 -0
  100. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/fastapi/endpoints.py +0 -0
  101. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/fastapi/response.py +0 -0
  102. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/fastapi/streaming.py +0 -0
  103. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/inference.py +0 -0
  104. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/pricing.py +0 -0
  105. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/registry.py +0 -0
  106. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/remote_auth.py +0 -0
  107. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/__init__.py +0 -0
  108. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_bounded.py +0 -0
  109. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_chain.py +0 -0
  110. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_conversation.py +0 -0
  111. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_grants.py +0 -0
  112. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_handle.py +0 -0
  113. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_health.py +0 -0
  114. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_hooks.py +0 -0
  115. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_lifecycle.py +0 -0
  116. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_limits.py +0 -0
  117. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/runtime/_mcp.py +0 -0
  118. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/validate/__init__.py +0 -0
  119. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/ai/validate/__main__.py +0 -0
  120. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/__init__.py +0 -0
  121. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/auto.py +0 -0
  122. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/bootstrap.py +0 -0
  123. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/config.py +0 -0
  124. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/constants.py +0 -0
  125. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/runner.py +0 -0
  126. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/celery/service.py +0 -0
  127. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/cli/__init__.py +0 -0
  128. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/cli/app.py +0 -0
  129. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/cli/check.py +0 -0
  130. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/cli/schema.py +0 -0
  131. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/async_bridge.py +0 -0
  132. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/__init__.py +0 -0
  133. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/_decide.py +0 -0
  134. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/_grants.py +0 -0
  135. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/_roles.py +0 -0
  136. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/_scope.py +0 -0
  137. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/elevation.py +0 -0
  138. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/authz/product.py +0 -0
  139. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/backend/__init__.py +0 -0
  140. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/backend/core_model.py +0 -0
  141. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/backend/protocol.py +0 -0
  142. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/backend/scoped_ddl.py +0 -0
  143. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/bootstrap/__init__.py +0 -0
  144. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
  145. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/bootstrap/kernel.py +0 -0
  146. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/__init__.py +0 -0
  147. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/_batching.py +0 -0
  148. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/_single_flight.py +0 -0
  149. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/abc/__init__.py +0 -0
  150. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/abc/backend.py +0 -0
  151. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/abc/config.py +0 -0
  152. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/abc/dependency.py +0 -0
  153. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/calls.py +0 -0
  154. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/codec.py +0 -0
  155. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/decorators.py +0 -0
  156. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/dependency.py +0 -0
  157. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/errors.py +0 -0
  158. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/gateway.py +0 -0
  159. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/keys.py +0 -0
  160. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/memory.py +0 -0
  161. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/repository.py +0 -0
  162. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/result_codec.py +0 -0
  163. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/serializer.py +0 -0
  164. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/cache/wiring.py +0 -0
  165. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/checks.py +0 -0
  166. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/command/__init__.py +0 -0
  167. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/command/adapter.py +0 -0
  168. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/command/base.py +0 -0
  169. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/command/field.py +0 -0
  170. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/command/introspection.py +0 -0
  171. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/compiler.py +0 -0
  172. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/__init__.py +0 -0
  173. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/_boto3.py +0 -0
  174. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/_includes.py +0 -0
  175. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/_resolver_utils.py +0 -0
  176. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/binder.py +0 -0
  177. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/configurable.py +0 -0
  178. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/context.py +0 -0
  179. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/errors.py +0 -0
  180. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/keys.py +0 -0
  181. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/loader.py +0 -0
  182. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/model.py +0 -0
  183. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/observability.py +0 -0
  184. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/overrides.py +0 -0
  185. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/resolver.py +0 -0
  186. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/secrets.py +0 -0
  187. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/config/ssm.py +0 -0
  188. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/contracts/__init__.py +0 -0
  189. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/contracts/manifest.py +0 -0
  190. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/di/__init__.py +0 -0
  191. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/di/container.py +0 -0
  192. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/di/scope.py +0 -0
  193. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/__init__.py +0 -0
  194. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/_utils.py +0 -0
  195. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/base.py +0 -0
  196. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/interfaces.py +0 -0
  197. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/manifest.py +0 -0
  198. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/discovery/modules.py +0 -0
  199. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/__init__.py +0 -0
  200. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/compilable.py +0 -0
  201. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/compiler.py +0 -0
  202. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/events.py +0 -0
  203. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/executor.py +0 -0
  204. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/metrics.py +0 -0
  205. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/plan.py +0 -0
  206. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/engine/post_commit.py +0 -0
  207. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/environment.py +0 -0
  208. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/errors/__init__.py +0 -0
  209. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/errors/codes.py +0 -0
  210. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/errors/errors.py +0 -0
  211. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/expr/__init__.py +0 -0
  212. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/expr/eval.py +0 -0
  213. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/expr/nodes.py +0 -0
  214. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/expr/refs.py +0 -0
  215. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/identity/__init__.py +0 -0
  216. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/identity/context.py +0 -0
  217. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/identity/identity.py +0 -0
  218. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/identity/issuer.py +0 -0
  219. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/identity/wire.py +0 -0
  220. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/introspection/__init__.py +0 -0
  221. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/introspection/base.py +0 -0
  222. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/introspection/describe.py +0 -0
  223. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/__init__.py +0 -0
  224. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/callback.py +0 -0
  225. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/context.py +0 -0
  226. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/handle.py +0 -0
  227. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/job.py +0 -0
  228. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/job/service.py +0 -0
  229. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/locator.py +0 -0
  230. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/__init__.py +0 -0
  231. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/abc.py +0 -0
  232. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/checks.py +0 -0
  233. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/config.py +0 -0
  234. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/registry.py +0 -0
  235. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/logger/structlogger.py +0 -0
  236. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/_json_schema.py +0 -0
  237. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/base.py +0 -0
  238. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/convert.py +0 -0
  239. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/enums.py +0 -0
  240. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/field.py +0 -0
  241. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/partition.py +0 -0
  242. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/privilege.py +0 -0
  243. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/projection.py +0 -0
  244. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/relation.py +0 -0
  245. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/scoped.py +0 -0
  246. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/struct.py +0 -0
  247. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/timestamped.py +0 -0
  248. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/model/types_postgres.py +0 -0
  249. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/__init__.py +0 -0
  250. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/config.py +0 -0
  251. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/event.py +0 -0
  252. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/observer/__init__.py +0 -0
  253. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/observer/noop.py +0 -0
  254. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/observer/otel.py +0 -0
  255. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/observer/structlog.py +0 -0
  256. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/otel_ids.py +0 -0
  257. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/protocol.py +0 -0
  258. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/runtime.py +0 -0
  259. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/span.py +0 -0
  260. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/observability/topology.py +0 -0
  261. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/persistence/__init__.py +0 -0
  262. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/persistence/abc.py +0 -0
  263. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/persistence/none.py +0 -0
  264. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/persistence/registry.py +0 -0
  265. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/plugins/__init__.py +0 -0
  266. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/plugins/entrypoints.py +0 -0
  267. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/plugins/optional.py +0 -0
  268. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/projection/__init__.py +0 -0
  269. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/projection/loaders.py +0 -0
  270. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/projection/runtime.py +0 -0
  271. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/__init__.py +0 -0
  272. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/__init__.py +0 -0
  273. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/cursor.py +0 -0
  274. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/errors.py +0 -0
  275. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/query.py +0 -0
  276. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/query_compiler.py +0 -0
  277. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/repo_for.py +0 -0
  278. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/repository.py +0 -0
  279. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/abc/session_scope.py +0 -0
  280. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/dynamodb/__init__.py +0 -0
  281. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/dynamodb/backend.py +0 -0
  282. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/dynamodb/registry.py +0 -0
  283. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/dynamodb/repository.py +0 -0
  284. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/dynamodb/uow.py +0 -0
  285. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/__init__.py +0 -0
  286. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/backend.py +0 -0
  287. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/ids.py +0 -0
  288. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/query_compiler.py +0 -0
  289. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/registry.py +0 -0
  290. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/repository.py +0 -0
  291. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/uow.py +0 -0
  292. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mongo/values.py +0 -0
  293. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/mutation.py +0 -0
  294. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/registration.py +0 -0
  295. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/registry.py +0 -0
  296. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
  297. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
  298. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
  299. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/migrations/__init__.py +0 -0
  300. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/migrations/env_template.py +0 -0
  301. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/migrations/hook.py +0 -0
  302. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/migrations/operations.py +0 -0
  303. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/migrations/runners.py +0 -0
  304. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
  305. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
  306. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
  307. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
  308. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +0 -0
  309. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +0 -0
  310. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
  311. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
  312. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
  313. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
  314. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/registry.py +0 -0
  315. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/repository.py +0 -0
  316. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/__init__.py +0 -0
  317. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/bootstrap.py +0 -0
  318. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/config.py +0 -0
  319. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/elevate.py +0 -0
  320. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0001.sql +0 -0
  321. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/0002.sql +0 -0
  322. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/guard/preflight.sql +0 -0
  323. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/guard_manifest.py +0 -0
  324. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/integrity.py +0 -0
  325. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/partitions.py +0 -0
  326. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/provider.py +0 -0
  327. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/schema.py +0 -0
  328. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/sources.py +0 -0
  329. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/rls/verify.py +0 -0
  330. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/session_manager.py +0 -0
  331. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/session_settings.py +0 -0
  332. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
  333. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
  334. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/response/__init__.py +0 -0
  335. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/response/base.py +0 -0
  336. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/routing/__init__.py +0 -0
  337. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/routing/ref.py +0 -0
  338. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/routing/resolver.py +0 -0
  339. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/runner.py +0 -0
  340. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/schema/__init__.py +0 -0
  341. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/schema/schema_mode.py +0 -0
  342. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/schema_names.py +0 -0
  343. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/__init__.py +0 -0
  344. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/abc/__init__.py +0 -0
  345. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/abc/contracts.py +0 -0
  346. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/abc/errors.py +0 -0
  347. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/caller_bound.py +0 -0
  348. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/clickhouse/__init__.py +0 -0
  349. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/clickhouse/_client.py +0 -0
  350. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/clickhouse/executor.py +0 -0
  351. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/clickhouse/registry.py +0 -0
  352. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/config.py +0 -0
  353. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/roles.py +0 -0
  354. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/sql/service.py +0 -0
  355. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/symbols.py +0 -0
  356. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/tracing/__init__.py +0 -0
  357. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/tracing/context.py +0 -0
  358. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/transaction.py +0 -0
  359. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/transport/__init__.py +0 -0
  360. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/transport/adapter.py +0 -0
  361. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/uow/__init__.py +0 -0
  362. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/uow/abc.py +0 -0
  363. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/uow/context.py +0 -0
  364. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/__init__.py +0 -0
  365. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/_predicates.py +0 -0
  366. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/agent_markers.py +0 -0
  367. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/compute.py +0 -0
  368. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/constants.py +0 -0
  369. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/factory.py +0 -0
  370. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/field_ref.py +0 -0
  371. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/invoker.py +0 -0
  372. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/keys.py +0 -0
  373. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/markers.py +0 -0
  374. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/mcp_markers.py +0 -0
  375. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/outcome.py +0 -0
  376. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/registry.py +0 -0
  377. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/rule.py +0 -0
  378. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/core/use_case/use_case.py +0 -0
  379. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/__init__.py +0 -0
  380. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/_uri.py +0 -0
  381. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/__init__.py +0 -0
  382. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_format_registry.py +0 -0
  383. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/__init__.py +0 -0
  384. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/_common.py +0 -0
  385. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/_log.py +0 -0
  386. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/_ops.py +0 -0
  387. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
  388. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_historify/_transform.py +0 -0
  389. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_merge.py +0 -0
  390. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_path_template.py +0 -0
  391. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_predicate.py +0 -0
  392. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
  393. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
  394. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_schema_aligner/_policy.py +0 -0
  395. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/_write_policy.py +0 -0
  396. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/__init__.py +0 -0
  397. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_dtype.py +0 -0
  398. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_file_writer.py +0 -0
  399. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_frame.py +0 -0
  400. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_historify.py +0 -0
  401. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_predicate.py +0 -0
  402. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_reader.py +0 -0
  403. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_schema.py +0 -0
  404. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
  405. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_streaming.py +0 -0
  406. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/_writer.py +0 -0
  407. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/polars/provider.py +0 -0
  408. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/__init__.py +0 -0
  409. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_dtype.py +0 -0
  410. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_historify.py +0 -0
  411. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_reader.py +0 -0
  412. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_schema.py +0 -0
  413. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
  414. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/_writer.py +0 -0
  415. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/backends/spark/provider.py +0 -0
  416. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/__init__.py +0 -0
  417. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
  418. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
  419. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_cleaners.py +0 -0
  420. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_options.py +0 -0
  421. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_paths.py +0 -0
  422. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_scope.py +0 -0
  423. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/checkpoint/_store.py +0 -0
  424. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/__init__.py +0 -0
  425. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_binding.py +0 -0
  426. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_compiler.py +0 -0
  427. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_errors.py +0 -0
  428. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_filter.py +0 -0
  429. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_plan.py +0 -0
  430. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_validators.py +0 -0
  431. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_validators_agents.py +0 -0
  432. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_validators_config.py +0 -0
  433. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_validators_plan.py +0 -0
  434. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/compiler/_validators_step.py +0 -0
  435. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/__init__.py +0 -0
  436. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/_format.py +0 -0
  437. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/_read_options.py +0 -0
  438. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/_utils.py +0 -0
  439. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/_with_agent.py +0 -0
  440. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/_write_options.py +0 -0
  441. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/expr/__init__.py +0 -0
  442. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/expr/_params.py +0 -0
  443. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/expr/_predicate.py +0 -0
  444. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
  445. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/expr/_refs.py +0 -0
  446. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/__init__.py +0 -0
  447. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_from.py +0 -0
  448. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -0
  449. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_from_config.py +0 -0
  450. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_from_dynamodb.py +0 -0
  451. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
  452. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/source/_specs.py +0 -0
  453. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/__init__.py +0 -0
  454. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_client.py +0 -0
  455. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_errors.py +0 -0
  456. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_file.py +0 -0
  457. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
  458. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/_builder.py +0 -0
  459. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
  460. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
  461. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/_report.py +0 -0
  462. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_history/_spec.py +0 -0
  463. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_into.py +0 -0
  464. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_schema_mode.py +0 -0
  465. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_table.py +0 -0
  466. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/declarative/target/_temp.py +0 -0
  467. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/executor/__init__.py +0 -0
  468. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/executor/_agents.py +0 -0
  469. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/executor/_dispatcher.py +0 -0
  470. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/executor/_executor.py +0 -0
  471. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/__init__.py +0 -0
  472. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/_registry.py +0 -0
  473. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/__init__.py +0 -0
  474. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_clickhouse.py +0 -0
  475. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_dynamodb.py +0 -0
  476. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_dynamodb_items.py +0 -0
  477. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_dynamodb_predicate.py +0 -0
  478. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_mongo.py +0 -0
  479. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
  480. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
  481. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
  482. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/sources/_serialization.py +0 -0
  483. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/targets/__init__.py +0 -0
  484. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/io/targets/_clickhouse.py +0 -0
  485. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/__init__.py +0 -0
  486. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/_config.py +0 -0
  487. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/_observer.py +0 -0
  488. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/_records.py +0 -0
  489. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/sinks/__init__.py +0 -0
  490. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
  491. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/sinks/_table.py +0 -0
  492. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/lineage/sinks/_writer.py +0 -0
  493. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/__init__.py +0 -0
  494. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/_builder.py +0 -0
  495. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/_ops.py +0 -0
  496. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/_protocol.py +0 -0
  497. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/_runner.py +0 -0
  498. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/_step.py +0 -0
  499. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/backends/__init__.py +0 -0
  500. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/maintenance/backends/_delta_rs.py +0 -0
  501. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/__init__.py +0 -0
  502. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_generics.py +0 -0
  503. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_params.py +0 -0
  504. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_pipeline.py +0 -0
  505. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_process.py +0 -0
  506. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_sql.py +0 -0
  507. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_step.py +0 -0
  508. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_step_client.py +0 -0
  509. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/pipeline/_step_sql.py +0 -0
  510. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/__init__.py +0 -0
  511. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/_agents.py +0 -0
  512. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/_providers.py +0 -0
  513. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/_wiring.py +0 -0
  514. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/config_loader.py +0 -0
  515. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/core.py +0 -0
  516. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/errors.py +0 -0
  517. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runner/filtering.py +0 -0
  518. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runtime/__init__.py +0 -0
  519. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runtime/_config_values.py +0 -0
  520. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/runtime/contracts.py +0 -0
  521. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/schema/__init__.py +0 -0
  522. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/schema/_contract.py +0 -0
  523. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/schema/_schema.py +0 -0
  524. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/storage/__init__.py +0 -0
  525. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/storage/_config.py +0 -0
  526. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/storage/_file_locator.py +0 -0
  527. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/storage/_locator.py +0 -0
  528. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/storage/routing.py +0 -0
  529. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/__init__.py +0 -0
  530. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/_result.py +0 -0
  531. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/_runners.py +0 -0
  532. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/_scenario.py +0 -0
  533. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/_stubs.py +0 -0
  534. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/etl/testing/spark.py +0 -0
  535. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/__init__.py +0 -0
  536. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_async.py +0 -0
  537. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_config.py +0 -0
  538. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_ctx.py +0 -0
  539. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_flow_yaml.py +0 -0
  540. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_meta.py +0 -0
  541. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_placeholders.py +0 -0
  542. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/_summary.py +0 -0
  543. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/deploy/__init__.py +0 -0
  544. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/deploy/_discovery.py +0 -0
  545. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/deploy/_schedule.py +0 -0
  546. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/deploy/_yaml_etls.py +0 -0
  547. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/deploy/entrypoint.py +0 -0
  548. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/__init__.py +0 -0
  549. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_assemble.py +0 -0
  550. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_backfill.py +0 -0
  551. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_backfill_body.py +0 -0
  552. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_body.py +0 -0
  553. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_common.py +0 -0
  554. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_factory.py +0 -0
  555. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_hooks.py +0 -0
  556. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_maintenance.py +0 -0
  557. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_params.py +0 -0
  558. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_run_name.py +0 -0
  559. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_runtime.py +0 -0
  560. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_signature.py +0 -0
  561. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/flow/_stages.py +0 -0
  562. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/manifest/__init__.py +0 -0
  563. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/manifest/_model.py +0 -0
  564. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/manifest/_s3.py +0 -0
  565. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/manifest/_store.py +0 -0
  566. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/__init__.py +0 -0
  567. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_event.py +0 -0
  568. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_factory.py +0 -0
  569. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_format.py +0 -0
  570. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_port.py +0 -0
  571. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_slack.py +0 -0
  572. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/notify/_sns.py +0 -0
  573. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/observer/__init__.py +0 -0
  574. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/observer/_flow.py +0 -0
  575. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/observer/_logging_bridge.py +0 -0
  576. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/observer/_manifest.py +0 -0
  577. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prefect/observer/_task_run.py +0 -0
  578. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/__init__.py +0 -0
  579. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/_instruments.py +0 -0
  580. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/adapter.py +0 -0
  581. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/kafka.py +0 -0
  582. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/lifecycle.py +0 -0
  583. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/prometheus/middleware.py +0 -0
  584. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/py.typed +0 -0
  585. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/__init__.py +0 -0
  586. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/_body.py +0 -0
  587. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/adapter.py +0 -0
  588. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/auth/__init__.py +0 -0
  589. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/auth/abc.py +0 -0
  590. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/auth/config.py +0 -0
  591. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/auth/jwt.py +0 -0
  592. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/auth/middleware.py +0 -0
  593. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/autocrud.py +0 -0
  594. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/checks.py +0 -0
  595. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/compiler.py +0 -0
  596. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/config.py +0 -0
  597. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/constants.py +0 -0
  598. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/cors.py +0 -0
  599. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/errors.py +0 -0
  600. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/__init__.py +0 -0
  601. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/_errors.py +0 -0
  602. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/_exclusions.py +0 -0
  603. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/app.py +0 -0
  604. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/auto.py +0 -0
  605. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/health.py +0 -0
  606. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/openapi.py +0 -0
  607. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/response.py +0 -0
  608. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/router_runtime.py +0 -0
  609. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/fastapi/sql.py +0 -0
  610. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/middleware.py +0 -0
  611. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/model.py +0 -0
  612. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/rest/rest_adapter.py +0 -0
  613. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/__init__.py +0 -0
  614. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/__init__.py +0 -0
  615. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_adapter.py +0 -0
  616. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_batch_spans.py +0 -0
  617. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
  618. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
  619. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_errors.py +0 -0
  620. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_operators.py +0 -0
  621. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
  622. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_runtime_io.py +0 -0
  623. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
  624. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
  625. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
  626. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
  627. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
  628. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
  629. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
  630. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
  631. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/bytewax/runner.py +0 -0
  632. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/__init__.py +0 -0
  633. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/_bindings.py +0 -0
  634. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/_compiler.py +0 -0
  635. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/_errors.py +0 -0
  636. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/_plan.py +0 -0
  637. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/phases/build_plan.py +0 -0
  638. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/compiler/phases/validate.py +0 -0
  639. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/__init__.py +0 -0
  640. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/_errors.py +0 -0
  641. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/_exceptions.py +0 -0
  642. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/_message.py +0 -0
  643. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/_tracing.py +0 -0
  644. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/core/_typing.py +0 -0
  645. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/graph/__init__.py +0 -0
  646. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/graph/_flow.py +0 -0
  647. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/__init__.py +0 -0
  648. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_codec.py +0 -0
  649. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_config.py +0 -0
  650. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_errors.py +0 -0
  651. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_key_resolver.py +0 -0
  652. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_message.py +0 -0
  653. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_record.py +0 -0
  654. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/_wire.py +0 -0
  655. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/client/__init__.py +0 -0
  656. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/client/_consumer.py +0 -0
  657. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/client/_producer.py +0 -0
  658. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/client/_protocol.py +0 -0
  659. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/client/_retry.py +0 -0
  660. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/message/__init__.py +0 -0
  661. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/message/_consumer.py +0 -0
  662. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/message/_producer.py +0 -0
  663. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/kafka/message/_protocol.py +0 -0
  664. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/mongo/__init__.py +0 -0
  665. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
  666. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/mongo/_config.py +0 -0
  667. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/mongo/_event.py +0 -0
  668. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/mongo/_normalize.py +0 -0
  669. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/__init__.py +0 -0
  670. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_boundary.py +0 -0
  671. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_branches.py +0 -0
  672. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_broadcast.py +0 -0
  673. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_capabilities.py +0 -0
  674. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_decompose.py +0 -0
  675. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_expand_routes.py +0 -0
  676. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_expr_eval.py +0 -0
  677. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_fork.py +0 -0
  678. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_helpers.py +0 -0
  679. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_mongo.py +0 -0
  680. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_protocols.py +0 -0
  681. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_router.py +0 -0
  682. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_shape.py +0 -0
  683. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_sink.py +0 -0
  684. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_table/__init__.py +0 -0
  685. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_table/common.py +0 -0
  686. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_table/config.py +0 -0
  687. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/_with.py +0 -0
  688. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/nodes/refs.py +0 -0
  689. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/streaming/testing.py +0 -0
  690. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/__init__.py +0 -0
  691. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/agents.py +0 -0
  692. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/golden.py +0 -0
  693. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/http_harness.py +0 -0
  694. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/in_memory.py +0 -0
  695. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/repository_harness.py +0 -0
  696. {loom_kernel-6.0.2 → loom_kernel-8.0.0}/src/loom/testing/runner.py +0 -0
@@ -623,6 +623,46 @@
623
623
  settings take effect: `primary_key=True` adds the column to the primary key,
624
624
  which can turn a model's key composite, and `nullable=True` makes the column
625
625
  nullable. Review such fields before upgrading.
626
+ - **core:** a `date` field is inferred as a `Date` column and a `time` field
627
+ as a `Time` column (`loom.core.model.Date`, `loom.core.model.Time`, new),
628
+ where both used to be inferred as an unbounded `String`; an enum mixed with
629
+ `date` or `time` follows to `Date` or `Time`. The SQLAlchemy repository
630
+ binds `date` and `time` values natively, so on Postgres with asyncpg writing
631
+ either field failed (`expected str, got date`, and the same for `time`). The
632
+ SQLAlchemy repository now refuses a `time` that carries a UTC offset when it
633
+ is written to, or compared with, a column that would drop the offset, with a
634
+ `BoundaryValidationError` (a `ValueError`) naming the column and not the
635
+ value: `boundary_validation` for a write (REST answers `422`),
636
+ `query_validation` for a filter, `get_by`, `exists_by` or `list_paginated`
637
+ value (`400`). Without the check, Postgres and SQLite would store
638
+ `08:30+02:00` in a `Time` column as `08:30`, and an aware filter value would
639
+ match the row holding `08:30`. A JSON column and a `Time` column declared
640
+ with `ColumnType("Time", kwargs={"timezone": True})` accept it; the JSON
641
+ column keeps the written offset, and so does the `Time` column on Postgres
642
+ (`timetz`), which takes only a `time` with an offset: one without (naive, or
643
+ with a zone but no fixed offset) is refused the same way, under
644
+ `time must carry a UTC offset`, since asyncpg cannot encode it for `timetz`;
645
+ every refused column of a write is reported, in name order. On any other
646
+ dialect startup refuses a `Time(timezone=True)` column with a `ConfigError`
647
+ naming `table.column`, since the dialect would not keep the offset. A
648
+ `datetime` field (`DateTime(tz=True)`) keeps the instant on Postgres
649
+ (`timestamptz`) and MongoDB, read back in UTC, not the written offset.
650
+ `get_by`, `exists_by` and the `filters` of `list_paginated` now convert
651
+ their value as a write converts it, as `QuerySpec` filters already did, so a
652
+ plain `Enum` member matches the value the write stored instead of failing to
653
+ bind. A `list_paginated` filter, `get_by` or `exists_by` on a name that is
654
+ not a mapped column of the model (a missing field, a relation, an attribute
655
+ such as `metadata`) raises `ValueError` naming it. An existing Postgres
656
+ table holding these columns as `varchar` needs a migration: Alembic
657
+ autogenerate detects the type change, but Postgres refuses it without a
658
+ cast, so the revision passes `postgresql_using="c::date"` (`"c::time"` for a
659
+ `time` field) to `op.alter_column`, which is
660
+ `ALTER TABLE t ALTER COLUMN c TYPE date USING c::date`. `c::time` drops any
661
+ offset the stored text holds (`'08:30+02'::time` is `08:30`): check first
662
+ with `SELECT c FROM t WHERE c ~ '[+-]\d{2}(:?\d{2})?$'`, and if offsets are
663
+ present convert those rows deliberately (for example to UTC with
664
+ `(c::timetz AT TIME ZONE 'UTC')::time`) before changing the type. MongoDB is
665
+ unaffected: it stores `date` and `time` values as ISO 8601 strings.
626
666
 
627
667
  ### ai
628
668
 
@@ -909,6 +949,24 @@
909
949
 
910
950
  ### streaming
911
951
 
952
+ - **streaming:** `BatchExpandStep.execute` returns one list of payloads per
953
+ message of its batch, in batch order, instead of one flat list. List `i`
954
+ holds what `messages[i]` expands into; each output takes that message's
955
+ metadata, and an empty list filters the message out. A result whose length
956
+ differs from the batch, a flat list of payloads, a `Message` among the
957
+ outputs, or a `str`, `bytes`, `bytearray` or mapping in place of the result
958
+ or of one of its lists raises `TypeError`, and the batch becomes error
959
+ envelopes.
960
+
961
+ ```python
962
+ # before
963
+ def execute(self, messages: list[Message[Event]], **kwargs: object) -> list[Score]:
964
+ return [Score(value=m.payload.amount) for m in messages]
965
+
966
+ # after
967
+ def execute(self, messages: list[Message[Event]], **kwargs: object) -> list[list[Score]]:
968
+ return [[Score(value=m.payload.amount)] for m in messages]
969
+ ```
912
970
  - **streaming:** compile issues come from the code catalogue
913
971
  (`StreamingErrorCode.X.issue(...)`), and the compiler's private issue
914
972
  factories are removed. `loom.streaming.compiler.CompilationIssue` is a type
@@ -1367,6 +1425,14 @@
1367
1425
  `Drain` default failed with `ROUTER_BRANCH_SHAPE_DIVERGENCE`, and a step
1368
1426
  after a `Router` without a default whose branches all end their path failed
1369
1427
  with `SHAPE_MISMATCH`; both compile now.
1428
+ - **streaming:** a `BatchExpandStep` expands. Every output had to pair with
1429
+ one input message, so a step returning more or fewer outputs than its batch
1430
+ raised and each message of the batch became an error envelope. Under
1431
+ at-least-once delivery each source offset now completes once per output,
1432
+ after that output's write, and a message with no output completes its
1433
+ offset at the step, also when the batch holds several messages of one
1434
+ offset that an earlier expanding node produced. The new return type is under
1435
+ Behaviour changes.
1370
1436
 
1371
1437
  ### prefect
1372
1438
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: loom-kernel
3
- Version: 6.0.2
3
+ Version: 8.0.0
4
4
  Summary: Loom Python project
5
5
  License-File: LICENSE
6
6
  Classifier: Programming Language :: Python :: 3
@@ -15,6 +15,7 @@ from sqlalchemy import (
15
15
  CheckConstraint,
16
16
  Column,
17
17
  Constraint,
18
+ Date,
18
19
  DateTime,
19
20
  Float,
20
21
  ForeignKey,
@@ -27,6 +28,7 @@ from sqlalchemy import (
27
28
  String,
28
29
  Table,
29
30
  Text,
31
+ Time,
30
32
  UniqueConstraint,
31
33
  func,
32
34
  text,
@@ -80,7 +82,9 @@ _SA_TYPE_MAP: dict[str, type] = {
80
82
  "Text": Text,
81
83
  "JSON": JSON,
82
84
  "Bytes": LargeBinary,
85
+ "Date": Date,
83
86
  "DateTime": DateTime,
87
+ "Time": Time,
84
88
  "Numeric": Numeric,
85
89
  "Postgres.JSONB": PG_JSONB,
86
90
  "Postgres.UUID": PG_UUID,
@@ -44,6 +44,7 @@ from loom.core.model.types import (
44
44
  BigInteger,
45
45
  Boolean,
46
46
  Bytes,
47
+ Date,
47
48
  DateTime,
48
49
  Float,
49
50
  Integer,
@@ -51,6 +52,7 @@ from loom.core.model.types import (
51
52
  Numeric,
52
53
  String,
53
54
  Text,
55
+ Time,
54
56
  )
55
57
  from loom.core.model.types_postgres import Postgres
56
58
 
@@ -85,6 +87,7 @@ __all__ = [
85
87
  "ColumnField",
86
88
  "ScopedField",
87
89
  "ColumnType",
90
+ "Date",
88
91
  "DateTime",
89
92
  "Field",
90
93
  "Float",
@@ -105,6 +108,7 @@ __all__ = [
105
108
  "ServerOnUpdate",
106
109
  "String",
107
110
  "Text",
111
+ "Time",
108
112
  "UnsupportedBoundaryType",
109
113
  "get_column_fields",
110
114
  "get_id_attribute",
@@ -107,7 +107,9 @@ class BoundaryValidationError(LoomError, ValueError):
107
107
  reasons drop the detail pydantic derives from the input; the msgspec
108
108
  message is forwarded as one line, without the value msgspec echoes for an
109
109
  invalid enum value or tag. A message raised by the type's own validator
110
- keeps its text. It is also a
110
+ keeps its text. A repository raises it for a value its storage cannot
111
+ hold, such as the SQLAlchemy repository for a ``time`` whose UTC offset,
112
+ present or missing, its column cannot take. It is also a
111
113
  :class:`ValueError`, so an ``except ValueError`` that used to catch
112
114
  ``msgspec.ValidationError`` or ``pydantic.ValidationError`` keeps
113
115
  catching it.
@@ -31,11 +31,13 @@ from loom.core.model.types import (
31
31
  JSON,
32
32
  Boolean,
33
33
  Bytes,
34
+ Date,
34
35
  DateTime,
35
36
  Float,
36
37
  Integer,
37
38
  Numeric,
38
39
  String,
40
+ Time,
39
41
  )
40
42
  from loom.core.schema_names import sql_identifier
41
43
 
@@ -405,8 +407,8 @@ _SCALAR_TYPE_MAP: dict[type, ColumnType] = {
405
407
  bool: Boolean,
406
408
  bytes: Bytes,
407
409
  datetime: DateTime(tz=True),
408
- date: String(None),
409
- time: String(None),
410
+ date: Date,
411
+ time: Time,
410
412
  Decimal: Numeric(),
411
413
  }
412
414
 
@@ -20,6 +20,8 @@ Boolean = ColumnType("Boolean")
20
20
  Text = ColumnType("Text")
21
21
  JSON = ColumnType("JSON")
22
22
  Bytes = ColumnType("Bytes")
23
+ Date = ColumnType("Date")
24
+ Time = ColumnType("Time")
23
25
 
24
26
 
25
27
  def DateTime(*, tz: bool = True) -> ColumnType:
@@ -9,7 +9,7 @@ from contextlib import asynccontextmanager
9
9
  from typing import ClassVar, Final, Literal
10
10
 
11
11
  import msgspec
12
- from sqlalchemy import inspect, make_url, text
12
+ from sqlalchemy import MetaData, Time, inspect, make_url, text
13
13
  from sqlalchemy.ext.asyncio import AsyncConnection
14
14
 
15
15
  from loom.core.authz.elevation import ElevationSink
@@ -205,6 +205,31 @@ def startup_checks(
205
205
  return unprotected
206
206
 
207
207
 
208
+ def check_time_zone_columns(dialect: str, metadata: MetaData) -> None:
209
+ """Refuse a ``Time(timezone=True)`` column on a dialect that drops its offset.
210
+
211
+ Postgres stores such a column as ``time with time zone`` and keeps the
212
+ offset; SQLite ignores the zone and stores the time without it.
213
+
214
+ Raises:
215
+ ConfigError: When *metadata* holds such a column and *dialect* is not
216
+ Postgres, naming each ``table.column``.
217
+ """
218
+ if dialect == POSTGRES_DIALECT:
219
+ return
220
+ columns = sorted(
221
+ f"{table.name}.{column.name}"
222
+ for table in metadata.tables.values()
223
+ for column in table.columns
224
+ if isinstance(column.type, Time) and column.type.timezone
225
+ )
226
+ if columns:
227
+ raise ConfigError(
228
+ f"dialect {dialect!r} would drop the UTC offset of the Time(timezone=True) "
229
+ f"columns {', '.join(columns)}; declare a JSON column to keep the offset"
230
+ )
231
+
232
+
208
233
  @asynccontextmanager
209
234
  async def _lifespan(
210
235
  session_manager: SessionManager,
@@ -223,6 +248,7 @@ async def _lifespan(
223
248
  scoped,
224
249
  has_session_settings=session_manager.has_session_settings,
225
250
  )
251
+ check_time_zone_columns(session_manager.engine.dialect.name, get_metadata())
226
252
  if unprotected:
227
253
  _logger.warning(
228
254
  "scoped tables left unprotected on this dialect: %s", ", ".join(unprotected)
@@ -11,6 +11,7 @@ from sqlalchemy import update as sa_update
11
11
  from sqlalchemy.ext.asyncio import AsyncSession
12
12
 
13
13
  from loom.core.backend.sqlalchemy import get_compiled_core
14
+ from loom.core.errors.codes import ErrorCode
14
15
  from loom.core.model.convert import to_struct
15
16
  from loom.core.model.introspection import (
16
17
  get_column_fields,
@@ -33,7 +34,12 @@ from loom.core.repository.mutation import MutationEvent
33
34
  from loom.core.repository.sqlalchemy.integrity import handle_integrity_errors
34
35
  from loom.core.repository.sqlalchemy.query_compiler.compiler import QuerySpecCompiler
35
36
  from loom.core.repository.sqlalchemy.transactional import record_mutation
36
- from loom.core.repository.sqlalchemy.values import is_json_column, to_column_value
37
+ from loom.core.repository.sqlalchemy.values import (
38
+ check_time_offsets,
39
+ is_json_column,
40
+ to_column_value,
41
+ to_comparison_value,
42
+ )
37
43
 
38
44
  _SENTINEL = object()
39
45
  _TOTAL_COUNT_ALIAS = "__loom_total_count"
@@ -161,7 +167,14 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
161
167
  builtins = to_column_value(data)
162
168
  if not isinstance(builtins, dict):
163
169
  raise TypeError("Struct payload must serialize to dict")
164
- return self._encode_json_columns(_to_internal_field_names(type(data), builtins))
170
+ values = self._encode_json_columns(_to_internal_field_names(type(data), builtins))
171
+ sa_model = self._effective_sa_model
172
+ names = (self._column_field_names or frozenset()).intersection(values)
173
+ check_time_offsets(
174
+ ((getattr(sa_model, name), values[name]) for name in names),
175
+ code=ErrorCode.BOUNDARY_VALIDATION,
176
+ )
177
+ return values
165
178
  return data
166
179
 
167
180
  def _encode_json_columns(self, values: dict[str, Any]) -> dict[str, Any]:
@@ -174,10 +187,11 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
174
187
  """Resolve a model column attribute by field name.
175
188
 
176
189
  Raises:
177
- ValueError: If ``field`` does not exist on the SQLAlchemy model.
190
+ ValueError: If ``field`` is not a mapped column of the SQLAlchemy
191
+ model.
178
192
  """
179
193
  sa_model = self._effective_sa_model
180
- if not hasattr(sa_model, field):
194
+ if field not in inspect(sa_model).column_attrs:
181
195
  raise ValueError(f"Unknown field '{field}' for model '{self.model.__name__}'")
182
196
  return getattr(sa_model, field)
183
197
 
@@ -189,7 +203,12 @@ class SQLAlchemyContextMixin(Generic[OutputT, IdT]):
189
203
  """Apply page-mode filters to an offset items statement."""
190
204
  if not filter_params or not filter_params.filters:
191
205
  return items_stmt
192
- return items_stmt.filter_by(**filter_params.filters)
206
+ return items_stmt.filter_by(
207
+ **{
208
+ name: to_comparison_value(self._column_for_field(name), value)
209
+ for name, value in filter_params.filters.items()
210
+ }
211
+ )
193
212
 
194
213
  def _to_output(
195
214
  self,
@@ -441,7 +460,9 @@ class SQLAlchemyReadMixin(SQLAlchemyContextMixin[OutputT, IdT], Generic[OutputT,
441
460
  """Fetch one entity by equality over an arbitrary column field."""
442
461
  async with self._session_scope() as scoped_session:
443
462
  core_model = self._effective_core_model
444
- stmt = core_model.select(profile).where(self._column_for_field(field) == value).limit(1)
463
+ column = self._column_for_field(field)
464
+ stmt = core_model.select(profile).where(column == to_comparison_value(column, value))
465
+ stmt = stmt.limit(1)
445
466
  loaded = await core_model.fetch_one(scoped_session, stmt, profile=profile)
446
467
  return cast(OutputT | None, loaded)
447
468
 
@@ -575,7 +596,8 @@ class SQLAlchemyReadMixin(SQLAlchemyContextMixin[OutputT, IdT], Generic[OutputT,
575
596
 
576
597
  async def exists_by(self, field: str, value: Any) -> bool:
577
598
  """Check whether an entity exists by an arbitrary column field."""
578
- return await self._exists_where(self._column_for_field(field) == value)
599
+ column = self._column_for_field(field)
600
+ return await self._exists_where(column == to_comparison_value(column, value))
579
601
 
580
602
  async def _exists_where(self, clause: Any) -> bool:
581
603
  async with self._session_scope() as scoped_session:
@@ -15,7 +15,7 @@ from loom.core.repository.sqlalchemy.query_compiler.subquery import (
15
15
  compile_exists,
16
16
  compile_not_exists,
17
17
  )
18
- from loom.core.repository.sqlalchemy.values import is_json_column, to_column_value
18
+ from loom.core.repository.sqlalchemy.values import to_comparison_value
19
19
 
20
20
  _RELATION_OPS = frozenset([FilterOp.EXISTS, FilterOp.NOT_EXISTS])
21
21
  _SIMPLE_OPS: dict[FilterOp, Callable[[Any, Any], Any]] = {
@@ -50,6 +50,8 @@ def compile_filter_group(
50
50
  Raises:
51
51
  UnsafeFilterError: If a field is not in ``allowed_fields``.
52
52
  FilterPathError: If a field path cannot be resolved.
53
+ BoundaryValidationError: ``query_validation``, for a ``time`` whose
54
+ offset the compared column cannot take.
53
55
  """
54
56
  clauses = [_compile_spec(sa_model, spec, allowed_fields) for spec in group.filters]
55
57
  if group.op == "OR":
@@ -78,17 +80,22 @@ def _compile_spec(
78
80
  def _apply_op(col: Any, op: FilterOp, value: Any) -> Any:
79
81
  """Apply *op*, converting *value* as the repository converts a value it writes.
80
82
 
81
- A SQLAlchemy expression, and an ``IN`` value that is a string or not
82
- iterable, reach SQLAlchemy as they are.
83
+ A ``time`` whose offset the column cannot take is refused, as
84
+ :func:`to_comparison_value` refuses it. A SQLAlchemy expression, and an
85
+ ``IN`` value that is a string or not iterable, reach SQLAlchemy as they
86
+ are.
87
+
88
+ Raises:
89
+ ValueError: If *op* is not a supported operator.
90
+ BoundaryValidationError: ``query_validation``, for a refused ``time``.
83
91
  """
84
92
  handler = _SIMPLE_OPS.get(op)
85
93
  if handler is None:
86
94
  raise ValueError(f"Unsupported FilterOp: {op!r}")
87
95
  if isinstance(value, ClauseElement):
88
96
  return handler(col, value)
89
- json = is_json_column(col)
90
97
  if op is not FilterOp.IN:
91
- return handler(col, to_column_value(value, json=json))
98
+ return handler(col, to_comparison_value(col, value))
92
99
  if isinstance(value, str | bytes) or not isinstance(value, Iterable):
93
100
  return handler(col, value)
94
- return handler(col, [to_column_value(item, json=json) for item in value])
101
+ return handler(col, [to_comparison_value(col, item) for item in value])
@@ -0,0 +1,130 @@
1
+ """Column form of model values in SQLAlchemy rows.
2
+
3
+ SQLAlchemy binds ``bytes``, ``datetime``, ``date``, ``time``, ``Decimal`` and
4
+ ``UUID`` natively; every other value is reduced to msgspec builtins (an
5
+ ``Enum`` to its value, a struct to a dict). A JSON column holds builtins only,
6
+ so its values are reduced completely.
7
+
8
+ :func:`to_column_value` is the conversion the repository applies to a value it
9
+ writes, and :func:`to_comparison_value` the one it applies to a value compared
10
+ with a column (a filter, ``get_by``, ``exists_by``), so a comparison matches
11
+ exactly what the row holds.
12
+
13
+ A ``time`` with a UTC offset is refused for a column that cannot hold the
14
+ offset: SQL ``TIME`` without time zone (Postgres ``time``, SQLite text) stores
15
+ ``08:30+02:00`` as ``08:30``, and an aware value compared with it matches the
16
+ row holding ``08:30``. A JSON column, which keeps the ISO text, takes any
17
+ ``time``. A ``Time`` column with ``timezone=True`` (Postgres ``timetz``) takes
18
+ only a ``time`` with an offset: asyncpg cannot encode a naive one for it. The
19
+ SQLAlchemy backend refuses such a column at startup on any dialect other than
20
+ Postgres.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from collections.abc import Iterable
26
+ from datetime import date, datetime, time
27
+ from decimal import Decimal
28
+ from typing import Any
29
+ from uuid import UUID
30
+
31
+ import msgspec
32
+ from sqlalchemy import JSON, Time
33
+
34
+ from loom.core.errors.codes import ErrorCode
35
+ from loom.core.model import BoundaryValidationError
36
+
37
+ # Values SQLAlchemy binds natively; encoding them to strings breaks typed columns.
38
+ _NATIVE_COLUMN_TYPES = (bytes, datetime, date, time, Decimal, UUID)
39
+
40
+
41
+ def to_column_value(value: object, *, json: bool = False) -> Any:
42
+ """Return the form ``value`` takes in a column.
43
+
44
+ Args:
45
+ value: A model value or a filter value.
46
+ json: ``True`` when the column is a JSON column.
47
+
48
+ Returns:
49
+ ``value`` reduced to msgspec builtins, keeping the natively bound
50
+ types unless the column is a JSON column.
51
+ """
52
+ if json:
53
+ return msgspec.to_builtins(value)
54
+ return msgspec.to_builtins(value, builtin_types=_NATIVE_COLUMN_TYPES)
55
+
56
+
57
+ _OFFSET_REFUSED = "time must not carry a UTC offset"
58
+ _OFFSET_REQUIRED = "time must carry a UTC offset"
59
+
60
+
61
+ def check_time_offsets(bindings: Iterable[tuple[Any, object]], *, code: str) -> None:
62
+ """Raise when a time's offset, present or missing, does not fit the column it is bound to.
63
+
64
+ A JSON column takes any ``time``. A ``Time(timezone=True)`` column keeps the
65
+ offset and takes only a ``time`` that has one (``utcoffset()`` is not
66
+ ``None``); every other column drops the offset and takes only a ``time``
67
+ without one. A model that needs the offset declares a JSON column or
68
+ ``ColumnType("Time", kwargs={"timezone": True})`` (Postgres only); on
69
+ Postgres a ``datetime`` field keeps the instant instead. The error names
70
+ the columns, not the values.
71
+
72
+ Args:
73
+ bindings: ``(column, value)`` pairs, each a SQLAlchemy column or mapped
74
+ attribute and a value about to be written to or compared with it.
75
+ code: ``boundary_validation`` for written values, ``query_validation``
76
+ for compared values.
77
+
78
+ Raises:
79
+ BoundaryValidationError: With one violation per refused column, in
80
+ column name order.
81
+ """
82
+ violations = sorted(
83
+ (column.key, reason)
84
+ for column, value in bindings
85
+ if (reason := _time_offset_refusal(column, value)) is not None
86
+ )
87
+ if violations:
88
+ message = "; ".join(f"{name}: {reason}" for name, reason in violations)
89
+ raise BoundaryValidationError(message, tuple(violations), code=code)
90
+
91
+
92
+ def _time_offset_refusal(column: Any, value: object) -> str | None:
93
+ if not isinstance(value, time) or is_json_column(column):
94
+ return None
95
+ column_type = getattr(column, "type", None)
96
+ keeps_offset = isinstance(column_type, Time) and bool(column_type.timezone)
97
+ if (value.utcoffset() is not None) == keeps_offset:
98
+ return None
99
+ return _OFFSET_REQUIRED if keeps_offset else _OFFSET_REFUSED
100
+
101
+
102
+ def to_comparison_value(column: Any, value: object) -> Any:
103
+ """Return *value* in the form it is compared with *column*.
104
+
105
+ Refused as :func:`check_time_offsets` refuses it, and converted as
106
+ :func:`to_column_value` converts a written value. A refusal is raised under
107
+ ``query_validation`` whatever the value's source, so ``get_by`` and
108
+ ``exists_by`` called with a value from a command body raise it too.
109
+
110
+ Args:
111
+ column: A SQLAlchemy column or mapped attribute.
112
+ value: A filter or lookup value.
113
+
114
+ Raises:
115
+ BoundaryValidationError: ``query_validation``, for a ``time`` whose
116
+ offset *column* cannot take, as :func:`check_time_offsets` decides.
117
+ """
118
+ check_time_offsets(((column, value),), code=ErrorCode.QUERY_VALIDATION)
119
+ return to_column_value(value, json=is_json_column(column))
120
+
121
+
122
+ def is_json_column(column: object) -> bool:
123
+ """Whether *column*, a SQLAlchemy column or mapped attribute, holds JSON.
124
+
125
+ ``JSON`` and the dialect types derived from it (Postgres ``JSONB``) count.
126
+ """
127
+ return isinstance(getattr(column, "type", None), JSON)
128
+
129
+
130
+ __all__ = ["check_time_offsets", "is_json_column", "to_column_value", "to_comparison_value"]
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
36
36
 
37
37
  Stream: TypeAlias = Any
38
38
  AwaitT = TypeVar("AwaitT")
39
+ ExpandT = TypeVar("ExpandT", bound=Iterable[Any])
39
40
 
40
41
 
41
42
  @runtime_checkable
@@ -91,11 +92,8 @@ class _ExecutableBatchExpandStep(Protocol):
91
92
  self,
92
93
  messages: list[Message[StreamPayload]],
93
94
  **kwargs: object,
94
- ) -> (
95
- Iterable[StreamPayload | Message[StreamPayload]]
96
- | Awaitable[Iterable[StreamPayload | Message[StreamPayload]]]
97
- ):
98
- """Expand one batch into many payloads or replacement messages."""
95
+ ) -> Iterable[Iterable[StreamPayload]] | Awaitable[Iterable[Iterable[StreamPayload]]]:
96
+ """Expand each message of one batch into its own list of payloads."""
99
97
  ...
100
98
 
101
99
 
@@ -259,10 +257,9 @@ def _resolve_batch_result(
259
257
 
260
258
 
261
259
  def _resolve_expand_result(
262
- result: Iterable[StreamPayload | Message[StreamPayload]]
263
- | Awaitable[Iterable[StreamPayload | Message[StreamPayload]]],
260
+ result: ExpandT | Awaitable[ExpandT],
264
261
  node_type: str,
265
- ) -> Iterable[StreamPayload | Message[StreamPayload]]:
262
+ ) -> ExpandT:
266
263
  """Resolve a synchronous expanding result and reject awaitables."""
267
264
  if isinstance(result, Awaitable):
268
265
  raise TypeError(f"{node_type} returned an awaitable outside WithAsync.")
@@ -353,9 +350,11 @@ def _reconcile_fanout(
353
350
 
354
351
  An expanding node turns one input record into N outputs that all carry the
355
352
  same source offset, and every one of them completes that offset when it
356
- reaches a terminal. The tracker starts each record expecting a single
357
- completion, so accounting has to be corrected here — while the outputs are
358
- still a plain list and none of them can have reached a terminal yet.
353
+ reaches a terminal. Each input already owes one completion, and a batch can
354
+ hold several inputs of one offset when an earlier node expanded it, so per
355
+ offset the outputs are compared with the inputs: extra outputs fork the
356
+ difference, and missing ones complete it here — while the outputs are still
357
+ a plain list and none of them can have reached a terminal yet.
359
358
 
360
359
  Two failures this prevents, both silent:
361
360
 
@@ -372,20 +371,21 @@ def _reconcile_fanout(
372
371
  """
373
372
  if tracker is None:
374
373
  return
375
- produced: Counter[tuple[str, int, int]] = Counter()
376
- for item in results:
377
- key = _commit_key(item)
378
- if key is not None:
379
- produced[key] += 1
380
- for key, count in produced.items():
381
- if count > 1:
382
- tracker.fork(key[0], key[1], key[2], count - 1)
383
- for original in originals:
384
- key = _commit_key(original)
385
- if key is not None and key not in produced:
374
+ expected = _commit_key_counts(originals)
375
+ produced = _commit_key_counts(results)
376
+ for key in expected | produced:
377
+ delta = produced[key] - expected[key]
378
+ if delta > 0:
379
+ tracker.fork(key[0], key[1], key[2], delta)
380
+ for _ in range(-delta):
386
381
  tracker.complete(key[0], key[1], key[2])
387
382
 
388
383
 
384
+ def _commit_key_counts(items: Sequence[Any]) -> Counter[tuple[str, int, int]]:
385
+ """Count the items accountable for each source offset."""
386
+ return Counter(key for item in items if (key := _commit_key(item)) is not None)
387
+
388
+
389
389
  def _drop_and_commit(item: Any, tracker: CommitCompletionPort) -> tuple[()]:
390
390
  """Drop one item and mark it complete for commit tracking.
391
391
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Iterable
5
+ from collections.abc import Iterable, Mapping
6
6
  from typing import Any
7
7
 
8
8
  from bytewax.operators import flat_map
@@ -134,8 +134,6 @@ def _apply_expand_step(
134
134
 
135
135
  sid = _step_id(f"expand_{idx}_{name}", ctx)
136
136
  mapped = bw_map(sid, stream, step_fn)
137
- from bytewax.operators import flat_map
138
-
139
137
  flattened_stream = flat_map(_step_id(f"flatten_expand_{idx}", ctx), mapped, _identity)
140
138
  return _split_node_result(flattened_stream, sid, ctx, ErrorKind.TASK)
141
139
 
@@ -296,9 +294,44 @@ def _execute_batch_expand_step(
296
294
  correlation_id=messages[0].meta.correlation_id if messages else None,
297
295
  ):
298
296
  result = _resolve_expand_result(batch_expand_step.execute(messages), name)
299
- if not isinstance(result, Iterable):
300
- raise TypeError(f"{name} must return an iterable of payloads.")
301
- return _replace_payloads(messages, list(result))
297
+ return _outputs_per_message(messages, _result_list(result, name), name)
298
+
299
+
300
+ def _outputs_per_message(
301
+ messages: list[Message[StreamPayload]],
302
+ groups: list[Any],
303
+ name: str,
304
+ ) -> list[Message[StreamPayload]]:
305
+ """Give each output the metadata of the message whose list it is in.
306
+
307
+ ``groups[i]`` holds the outputs of ``messages[i]``; an empty list filters
308
+ that message out.
309
+ """
310
+ if len(groups) != len(messages):
311
+ raise TypeError(
312
+ f"{name} returned {len(groups)} output lists for {len(messages)} messages; "
313
+ "return one list of payloads per message, in batch order."
314
+ )
315
+ outputs: list[Message[StreamPayload]] = []
316
+ for message, payloads in zip(messages, groups, strict=True):
317
+ for payload in _result_list(payloads, name):
318
+ if isinstance(payload, Message):
319
+ raise TypeError(
320
+ f"{name} must return payloads, not messages: each output "
321
+ "takes the metadata of the message it came from."
322
+ )
323
+ outputs.append(_replace_payload(message, payload))
324
+ return outputs
325
+
326
+
327
+ def _result_list(value: object, name: str) -> list[Any]:
328
+ """Materialize one list of a batch-expanding result, iterating it once.
329
+
330
+ ``str``, ``bytes`` and mappings are iterable but are not lists of results.
331
+ """
332
+ if not isinstance(value, Iterable) or isinstance(value, (str, bytes, bytearray, Mapping)):
333
+ raise TypeError(f"{name} must return one list of payloads per message.")
334
+ return list(value)
302
335
 
303
336
 
304
337
  def _execute_explode_step(