reactifact 0.15.2__tar.gz → 0.15.3__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 (315) hide show
  1. {reactifact-0.15.2/reactifact.egg-info → reactifact-0.15.3}/PKG-INFO +18 -1
  2. {reactifact-0.15.2 → reactifact-0.15.3}/README.md +17 -0
  3. {reactifact-0.15.2 → reactifact-0.15.3}/pyproject.toml +1 -1
  4. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/__init__.py +1 -1
  5. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/audit.py +22 -2
  6. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/interrupt.py +12 -1
  7. {reactifact-0.15.2 → reactifact-0.15.3/reactifact.egg-info}/PKG-INFO +18 -1
  8. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_audit.py +33 -0
  9. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_outbox.py +10 -0
  10. {reactifact-0.15.2 → reactifact-0.15.3}/LICENSE +0 -0
  11. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/__main__.py +0 -0
  12. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/_extras.py +0 -0
  13. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/_httpx.py +0 -0
  14. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/a2a/__init__.py +0 -0
  15. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/a2a/client.py +0 -0
  16. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/a2a/models.py +0 -0
  17. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/a2a/remote.py +0 -0
  18. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/a2a/server.py +0 -0
  19. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/agent_tool.py +0 -0
  20. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/agents.py +0 -0
  21. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/artifacts.py +0 -0
  22. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/authz.py +0 -0
  23. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/branching.py +0 -0
  24. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/budget.py +0 -0
  25. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cache.py +0 -0
  26. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/chat.py +0 -0
  27. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/checkpoints.py +0 -0
  28. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/__init__.py +0 -0
  29. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/branch.py +0 -0
  30. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/common.py +0 -0
  31. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/context.py +0 -0
  32. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/eval.py +0 -0
  33. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/graph.py +0 -0
  34. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/replay.py +0 -0
  35. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/scenario.py +0 -0
  36. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/skills.py +0 -0
  37. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/cli/trace.py +0 -0
  38. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/commit.py +0 -0
  39. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/commit_log.py +0 -0
  40. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/consume.py +0 -0
  41. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/context.py +0 -0
  42. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/context_builder.py +0 -0
  43. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/effects.py +0 -0
  44. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/__init__.py +0 -0
  45. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/dataset.py +0 -0
  46. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/evaluators.py +0 -0
  47. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/judge.py +0 -0
  48. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/online.py +0 -0
  49. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/runner.py +0 -0
  50. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/eval/scoring.py +0 -0
  51. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/events.py +0 -0
  52. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/guardrails.py +0 -0
  53. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/llm_agent.py +0 -0
  54. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/logging.py +0 -0
  55. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/mcp/__init__.py +0 -0
  56. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/mcp/client.py +0 -0
  57. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/mcp/oauth.py +0 -0
  58. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/mcp/server.py +0 -0
  59. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/metrics.py +0 -0
  60. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/native_tool_use.py +0 -0
  61. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/operations.py +0 -0
  62. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/patches.py +0 -0
  63. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/pricing.py +0 -0
  64. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/produce.py +0 -0
  65. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/prompts.py +0 -0
  66. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/__init__.py +0 -0
  67. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/_retry.py +0 -0
  68. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/anthropic.py +0 -0
  69. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/azure.py +0 -0
  70. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/cerebras.py +0 -0
  71. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/chat.py +0 -0
  72. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/contracts.py +0 -0
  73. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/deepseek.py +0 -0
  74. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/fake.py +0 -0
  75. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/fireworks.py +0 -0
  76. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/gemini.py +0 -0
  77. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/github_models.py +0 -0
  78. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/groq.py +0 -0
  79. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/image.py +0 -0
  80. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/mistral.py +0 -0
  81. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/nvidia.py +0 -0
  82. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/ollama.py +0 -0
  83. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/openai.py +0 -0
  84. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/openrouter.py +0 -0
  85. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/perplexity.py +0 -0
  86. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/qwen.py +0 -0
  87. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/speech.py +0 -0
  88. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/together.py +0 -0
  89. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/video.py +0 -0
  90. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/xai.py +0 -0
  91. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/providers/zai.py +0 -0
  92. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/py.typed +0 -0
  93. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/__init__.py +0 -0
  94. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/_shared.py +0 -0
  95. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/agent.py +0 -0
  96. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/chat.py +0 -0
  97. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/models.py +0 -0
  98. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/rag.py +0 -0
  99. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quick/tools_agent.py +0 -0
  100. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/quota.py +0 -0
  101. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/__init__.py +0 -0
  102. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/cleanup.py +0 -0
  103. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/conversation.py +0 -0
  104. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/identity.py +0 -0
  105. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/inputs.py +0 -0
  106. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/memory.py +0 -0
  107. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/plan_execute.py +0 -0
  108. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/reflection.py +0 -0
  109. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/resolve.py +0 -0
  110. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/rollback.py +0 -0
  111. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/search.py +0 -0
  112. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/skills.py +0 -0
  113. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/status.py +0 -0
  114. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/supervisor.py +0 -0
  115. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/text.py +0 -0
  116. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/recipes/tool_loop.py +0 -0
  117. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/redaction.py +0 -0
  118. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/relations.py +0 -0
  119. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/replay.py +0 -0
  120. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/request.py +0 -0
  121. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/resources.py +0 -0
  122. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/routing.py +0 -0
  123. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/runtime.py +0 -0
  124. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/scheduler.py +0 -0
  125. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/session.py +0 -0
  126. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact/SKILL.md +0 -0
  127. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact/references/effects-and-state.md +0 -0
  128. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact/references/trust-and-safety.md +0 -0
  129. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-agents/SKILL.md +0 -0
  130. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-agents/references/consume.md +0 -0
  131. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-agents/references/effects.md +0 -0
  132. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-eval/SKILL.md +0 -0
  133. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-eval/references/online.md +0 -0
  134. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-from-langchain/SKILL.md +0 -0
  135. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-llm/SKILL.md +0 -0
  136. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-llm/references/providers.md +0 -0
  137. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-llm/references/tools.md +0 -0
  138. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-observability/SKILL.md +0 -0
  139. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-rag/SKILL.md +0 -0
  140. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-rag/references/sources.md +0 -0
  141. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/skills/reactifact-testing/SKILL.md +0 -0
  142. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/sources.py +0 -0
  143. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/streaming.py +0 -0
  144. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/structured.py +0 -0
  145. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/__init__.py +0 -0
  146. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/assertions.py +0 -0
  147. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/exceptions.py +0 -0
  148. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/fault.py +0 -0
  149. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/golden.py +0 -0
  150. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/lab.py +0 -0
  151. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/mock.py +0 -0
  152. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/pytest_plugin.py +0 -0
  153. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/record.py +0 -0
  154. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/testing/registry.py +0 -0
  155. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tool_use.py +0 -0
  156. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tools.py +0 -0
  157. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/__init__.py +0 -0
  158. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/_otlp.py +0 -0
  159. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/columns.py +0 -0
  160. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/langfuse.py +0 -0
  161. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/models.py +0 -0
  162. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/otlp.py +0 -0
  163. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/postgres.py +0 -0
  164. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/store.py +0 -0
  165. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/templates/app.css +0 -0
  166. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/templates/sessions.html +0 -0
  167. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/templates/ui.html +0 -0
  168. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/templates/ui_run.html +0 -0
  169. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/tracer.py +0 -0
  170. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/tracing/web.py +0 -0
  171. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/triggers.py +0 -0
  172. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/types.py +0 -0
  173. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/verify.py +0 -0
  174. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/viz.py +0 -0
  175. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact/web.py +0 -0
  176. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact.egg-info/SOURCES.txt +0 -0
  177. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact.egg-info/dependency_links.txt +0 -0
  178. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact.egg-info/entry_points.txt +0 -0
  179. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact.egg-info/requires.txt +0 -0
  180. {reactifact-0.15.2 → reactifact-0.15.3}/reactifact.egg-info/top_level.txt +0 -0
  181. {reactifact-0.15.2 → reactifact-0.15.3}/setup.cfg +0 -0
  182. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_a2a.py +0 -0
  183. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_a2a_example.py +0 -0
  184. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_a2a_interop.py +0 -0
  185. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_absent_consume.py +0 -0
  186. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_adaptive.py +0 -0
  187. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_agent_tool.py +0 -0
  188. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_anthropic_provider.py +0 -0
  189. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_artifacts.py +0 -0
  190. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_authz.py +0 -0
  191. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_backbone.py +0 -0
  192. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_branching.py +0 -0
  193. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_budget.py +0 -0
  194. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_cache.py +0 -0
  195. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_canonical_ports.py +0 -0
  196. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_chat_example.py +0 -0
  197. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_chat_memory.py +0 -0
  198. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_chat_outbox.py +0 -0
  199. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_chat_web.py +0 -0
  200. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_checkpoint.py +0 -0
  201. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_checkpoints_concurrency.py +0 -0
  202. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_cli.py +0 -0
  203. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_cli_scenario.py +0 -0
  204. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_commit_log.py +0 -0
  205. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_compaction.py +0 -0
  206. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_concurrency.py +0 -0
  207. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_consumes_produces.py +0 -0
  208. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_context_builder.py +0 -0
  209. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_correlated_consume.py +0 -0
  210. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_debounce.py +0 -0
  211. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_determinism.py +0 -0
  212. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_devops.py +0 -0
  213. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_devops_online.py +0 -0
  214. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_devops_web.py +0 -0
  215. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_effects.py +0 -0
  216. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_eval.py +0 -0
  217. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_eval_dataset.py +0 -0
  218. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_eval_judge.py +0 -0
  219. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_eval_online.py +0 -0
  220. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_eval_trajectory.py +0 -0
  221. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_fintech_audit.py +0 -0
  222. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_forklab.py +0 -0
  223. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_forklab_web.py +0 -0
  224. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_friendly_api.py +0 -0
  225. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_gemini_provider.py +0 -0
  226. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_golden.py +0 -0
  227. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_guardrails.py +0 -0
  228. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_hitl.py +0 -0
  229. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_image_provider.py +0 -0
  230. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_incident_commander.py +0 -0
  231. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_invalidation.py +0 -0
  232. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_join_consume.py +0 -0
  233. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_knowledge.py +0 -0
  234. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_knowledge_web.py +0 -0
  235. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_llm_ladder.py +0 -0
  236. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_logging.py +0 -0
  237. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_loop_bound_client.py +0 -0
  238. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_mcp.py +0 -0
  239. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_medic_lab.py +0 -0
  240. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_medic_lab_web.py +0 -0
  241. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_metrics.py +0 -0
  242. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_multisource.py +0 -0
  243. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_native_tool_use.py +0 -0
  244. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_openai_provider.py +0 -0
  245. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_patches.py +0 -0
  246. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_pending_actions.py +0 -0
  247. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_ports.py +0 -0
  248. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_produce_styles.py +0 -0
  249. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_produce_trigger.py +0 -0
  250. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_prompts.py +0 -0
  251. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_provider_auth.py +0 -0
  252. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_provider_retry.py +0 -0
  253. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_providers_integration.py +0 -0
  254. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_public_api.py +0 -0
  255. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_quick.py +0 -0
  256. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_quota.py +0 -0
  257. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_reacts_to.py +0 -0
  258. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipe_conversation.py +0 -0
  259. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipe_plan_execute.py +0 -0
  260. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipe_reflection.py +0 -0
  261. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipe_supervisor.py +0 -0
  262. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipe_tool_loop.py +0 -0
  263. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipes.py +0 -0
  264. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipes_inputs.py +0 -0
  265. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipes_memory.py +0 -0
  266. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_recipes_skills.py +0 -0
  267. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_redaction.py +0 -0
  268. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_relation_graph.py +0 -0
  269. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_relations.py +0 -0
  270. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_repair.py +0 -0
  271. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_repair_web.py +0 -0
  272. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_replay.py +0 -0
  273. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_repo_agent.py +0 -0
  274. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_request.py +0 -0
  275. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_research.py +0 -0
  276. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_resources.py +0 -0
  277. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_retry.py +0 -0
  278. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_routing.py +0 -0
  279. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_runtime.py +0 -0
  280. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_runtime_errors.py +0 -0
  281. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_scheduler_semantics.py +0 -0
  282. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_sessions.py +0 -0
  283. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_shutdown.py +0 -0
  284. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_skills.py +0 -0
  285. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_sources.py +0 -0
  286. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_sources_search.py +0 -0
  287. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_sources_vector.py +0 -0
  288. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_speech_provider.py +0 -0
  289. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_starter_app.py +0 -0
  290. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_streaming.py +0 -0
  291. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_structured.py +0 -0
  292. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_support_copilot.py +0 -0
  293. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_assertions.py +0 -0
  294. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_golden.py +0 -0
  295. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_lab.py +0 -0
  296. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_mock.py +0 -0
  297. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_provenance.py +0 -0
  298. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_pytest_plugin.py +0 -0
  299. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_testing_registry.py +0 -0
  300. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_token_budget.py +0 -0
  301. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_tools.py +0 -0
  302. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_trace_columns.py +0 -0
  303. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_trace_tags.py +0 -0
  304. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_tracing.py +0 -0
  305. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_type_registry.py +0 -0
  306. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_vendor_factories.py +0 -0
  307. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_vendor_multimodal_factories.py +0 -0
  308. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_verify.py +0 -0
  309. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_video_provider.py +0 -0
  310. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_view.py +0 -0
  311. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_viz.py +0 -0
  312. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_web_source.py +0 -0
  313. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_workspace.py +0 -0
  314. {reactifact-0.15.2 → reactifact-0.15.3}/tests/test_workspace_with_sources.py +0 -0
  315. {reactifact-0.15.2 → reactifact-0.15.3}/tests/tests_checkpoints_sqlite.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reactifact
3
- Version: 0.15.2
3
+ Version: 0.15.3
4
4
  Summary: Reactive, artifact-driven agent runtime: agents transform versioned, typed, provenance-aware artifacts inside an evolving context
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/bzdvdn/reactifact
@@ -323,6 +323,23 @@ by hand. Run it yourself: `uv run python -m examples.ledger.main`.
323
323
  - **Viz & CLI** — Mermaid `blueprint`/`context_to_mermaid`/`trace_to_mermaid`;
324
324
  `reactifact` with `graph`/`context`/`trace`/`replay`/`branch`.
325
325
 
326
+ ## Agent Skills
327
+
328
+ reactifact ships official **Agent Skills** — reusable instructions that teach a
329
+ coding agent (Claude Code, Cursor, Codex, Copilot, …) how to build *with*
330
+ reactifact. They're bundled with the package, so they always match your version:
331
+
332
+ ```bash
333
+ python -m reactifact skills list # what is available
334
+ python -m reactifact skills install # -> .agents/skills/
335
+ python -m reactifact skills install --target both # + .claude/skills/
336
+ ```
337
+
338
+ Skills: `reactifact` (mental model), `reactifact-agents`, `reactifact-llm`,
339
+ `reactifact-rag`, `reactifact-testing`, `reactifact-eval`,
340
+ `reactifact-observability`, `reactifact-from-langchain` — see
341
+ [Agent skills](docs/en/skills.md).
342
+
326
343
  ## Run a demo
327
344
 
328
345
  Offline-capable, no API keys required (deterministic fallbacks):
@@ -277,6 +277,23 @@ by hand. Run it yourself: `uv run python -m examples.ledger.main`.
277
277
  - **Viz & CLI** — Mermaid `blueprint`/`context_to_mermaid`/`trace_to_mermaid`;
278
278
  `reactifact` with `graph`/`context`/`trace`/`replay`/`branch`.
279
279
 
280
+ ## Agent Skills
281
+
282
+ reactifact ships official **Agent Skills** — reusable instructions that teach a
283
+ coding agent (Claude Code, Cursor, Codex, Copilot, …) how to build *with*
284
+ reactifact. They're bundled with the package, so they always match your version:
285
+
286
+ ```bash
287
+ python -m reactifact skills list # what is available
288
+ python -m reactifact skills install # -> .agents/skills/
289
+ python -m reactifact skills install --target both # + .claude/skills/
290
+ ```
291
+
292
+ Skills: `reactifact` (mental model), `reactifact-agents`, `reactifact-llm`,
293
+ `reactifact-rag`, `reactifact-testing`, `reactifact-eval`,
294
+ `reactifact-observability`, `reactifact-from-langchain` — see
295
+ [Agent skills](docs/en/skills.md).
296
+
280
297
  ## Run a demo
281
298
 
282
299
  Offline-capable, no API keys required (deterministic fallbacks):
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "reactifact"
7
- version = "0.15.2"
7
+ version = "0.15.3"
8
8
  description = "Reactive, artifact-driven agent runtime: agents transform versioned, typed, provenance-aware artifacts inside an evolving context"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -51,7 +51,7 @@ from .tools import FunctionTool, Tool, ToolOutput, tool
51
51
  from .triggers import Trigger
52
52
  from .types import register as register_type
53
53
 
54
- __version__ = "0.15.2"
54
+ __version__ = "0.15.3"
55
55
 
56
56
  __all__ = [
57
57
  "Agent",
@@ -47,10 +47,30 @@ DEFAULT_RELATIONS: tuple[str, ...] = (
47
47
  )
48
48
 
49
49
 
50
+ def _transient_fields(model: type[BaseModel]) -> set[str]:
51
+ """Field names a model declares as transactional *envelope*, not state.
52
+
53
+ A model lists them as ``transient_fields: ClassVar[frozenset[str]]``
54
+ (e.g. `PendingAction.dispatched_at`, `PendingQuestion.resolved_at`).
55
+ Wall-clock transitions are excluded from the content hash so an otherwise
56
+ identical state doesn't hash differently run to run — the *fact* of the
57
+ transition stays hashed (`status`/`resolution`); only its timestamp drops.
58
+ """
59
+ names = getattr(model, "transient_fields", ())
60
+ return set(names) if names else set()
61
+
62
+
50
63
  def _canonical(value: Any) -> str:
51
- """Canonical JSON for hashing (sorted keys; pydantic models dumped)."""
64
+ """Canonical JSON for hashing (sorted keys; pydantic models dumped).
65
+
66
+ A model's `transient_fields` are dropped before hashing — envelope, not
67
+ state. Everything else is serialized exactly as before, so a state with no
68
+ transient fields hashes the same as it always did.
69
+ """
52
70
  if isinstance(value, BaseModel):
53
- payload: Any = value.model_dump(mode="json")
71
+ payload: Any = value.model_dump(
72
+ mode="json", exclude=_transient_fields(type(value)) or None
73
+ )
54
74
  else:
55
75
  payload = value
56
76
  return json.dumps(payload, sort_keys=True, ensure_ascii=False, default=str)
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
- from typing import Any, Literal
4
+ from typing import Any, ClassVar, Literal
5
5
 
6
6
  from pydantic import BaseModel, Field
7
7
 
@@ -21,6 +21,11 @@ class PendingQuestion(BaseModel):
21
21
  resolution: str | None = None
22
22
  resolved_at: datetime | None = None
23
23
 
24
+ #: Wall-clock fields excluded from `context_hash` (transactional envelope,
25
+ #: not state): a resolved question's *state* is `resolution`, the moment it
26
+ #: was resolved is not something two equivalent runs must agree on.
27
+ transient_fields: ClassVar[frozenset[str]] = frozenset({"resolved_at"})
28
+
24
29
 
25
30
  class PendingAction(BaseModel):
26
31
  """An outbound side effect awaiting dispatch (outbox, §42/§55/§59).
@@ -52,3 +57,9 @@ class PendingAction(BaseModel):
52
57
  attempts: int = 0
53
58
  dispatched_at: datetime | None = None
54
59
  error: str | None = None
60
+
61
+ #: Wall-clock field excluded from `context_hash` (transactional envelope,
62
+ #: not state): the *fact* that the action dispatched (`status`/`error`/
63
+ #: `attempts`) is hashed, the moment it happened is not — so an outbox run
64
+ #: stays run-to-run reproducible.
65
+ transient_fields: ClassVar[frozenset[str]] = frozenset({"dispatched_at"})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reactifact
3
- Version: 0.15.2
3
+ Version: 0.15.3
4
4
  Summary: Reactive, artifact-driven agent runtime: agents transform versioned, typed, provenance-aware artifacts inside an evolving context
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/bzdvdn/reactifact
@@ -323,6 +323,23 @@ by hand. Run it yourself: `uv run python -m examples.ledger.main`.
323
323
  - **Viz & CLI** — Mermaid `blueprint`/`context_to_mermaid`/`trace_to_mermaid`;
324
324
  `reactifact` with `graph`/`context`/`trace`/`replay`/`branch`.
325
325
 
326
+ ## Agent Skills
327
+
328
+ reactifact ships official **Agent Skills** — reusable instructions that teach a
329
+ coding agent (Claude Code, Cursor, Codex, Copilot, …) how to build *with*
330
+ reactifact. They're bundled with the package, so they always match your version:
331
+
332
+ ```bash
333
+ python -m reactifact skills list # what is available
334
+ python -m reactifact skills install # -> .agents/skills/
335
+ python -m reactifact skills install --target both # + .claude/skills/
336
+ ```
337
+
338
+ Skills: `reactifact` (mental model), `reactifact-agents`, `reactifact-llm`,
339
+ `reactifact-rag`, `reactifact-testing`, `reactifact-eval`,
340
+ `reactifact-observability`, `reactifact-from-langchain` — see
341
+ [Agent skills](docs/en/skills.md).
342
+
326
343
  ## Run a demo
327
344
 
328
345
  Offline-capable, no API keys required (deterministic fallbacks):
@@ -88,6 +88,39 @@ def test_context_hash_changes_when_state_changes():
88
88
  assert context_hash(before) != context_hash(after)
89
89
 
90
90
 
91
+ def test_transient_wall_clock_fields_are_excluded_from_the_hash():
92
+ """`dispatched_at`/`resolved_at` are envelope, not state: two records that
93
+ differ only in those timestamps hash the same; a real state change does not."""
94
+ from datetime import UTC, datetime, timedelta
95
+
96
+ from reactifact import PendingAction
97
+ from reactifact.interrupt import PendingQuestion
98
+
99
+ now = datetime.now(UTC)
100
+ later = now + timedelta(seconds=5)
101
+
102
+ dispatched = PendingAction(
103
+ kind="notify", idempotency_key="k", status="dispatched", dispatched_at=now
104
+ )
105
+ dispatched_later = PendingAction(
106
+ kind="notify", idempotency_key="k", status="dispatched", dispatched_at=later
107
+ )
108
+ assert data_hash(dispatched) == data_hash(dispatched_later)
109
+
110
+ failed = PendingAction(
111
+ kind="notify", idempotency_key="k", status="failed", dispatched_at=now
112
+ )
113
+ assert data_hash(dispatched) != data_hash(failed)
114
+
115
+ answered = PendingQuestion(
116
+ question="q", answered=True, resolution="yes", resolved_at=now
117
+ )
118
+ answered_later = PendingQuestion(
119
+ question="q", answered=True, resolution="yes", resolved_at=later
120
+ )
121
+ assert data_hash(answered) == data_hash(answered_later)
122
+
123
+
91
124
  # --- report ----------------------------------------------------------------- #
92
125
 
93
126
 
@@ -13,6 +13,7 @@ from examples.outbox.main import (
13
13
  same_generation,
14
14
  )
15
15
  from reactifact import PendingAction
16
+ from reactifact.audit import context_hash
16
17
 
17
18
 
18
19
  def test_happy_path_sends_once():
@@ -63,3 +64,12 @@ def test_app_owned_retry_absorbs_transient_failures():
63
64
  assert status == "dispatched"
64
65
  assert attempts == 0 # the wrapper absorbed the failures, runtime saw one outcome
65
66
  assert log.keys() == ["notify:77"]
67
+
68
+
69
+ def test_dispatch_is_reproducible_despite_wall_clock():
70
+ """A dispatched outbox run hashes identically run to run: the transition is
71
+ hashed, its wall-clock timestamp (`dispatched_at`) is not."""
72
+ first, _ = asyncio.run(happy_path())
73
+ second, _ = asyncio.run(happy_path())
74
+ assert first.get(ACTION).data.status == "dispatched"
75
+ assert context_hash(first) == context_hash(second)
File without changes