AbstractRuntime 0.8.2__tar.gz → 0.8.4__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 (679) hide show
  1. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/.github/workflows/ci.yml +1 -0
  2. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/CHANGELOG.md +22 -0
  3. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/PKG-INFO +1 -1
  4. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/automations.md +15 -4
  5. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/llms-full.txt +15 -4
  6. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/llms.txt +1 -1
  7. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/pyproject.toml +1 -1
  8. abstractruntime-0.8.4/release-notes.md +2 -0
  9. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automation_queries.py +2 -0
  10. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/attention.py +3 -0
  11. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/controller.py +33 -6
  12. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/models.py +15 -6
  13. abstractruntime-0.8.4/src/abstractruntime/integrations/abstractcore/mcp_facade.py +120 -0
  14. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_definition.py +13 -0
  15. abstractruntime-0.8.4/tests/test_automation_email_results.py +59 -0
  16. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_growing_context.py +39 -0
  17. abstractruntime-0.8.4/tests/test_mcp_runs_untrusted_and_facade.py +119 -0
  18. abstractruntime-0.8.2/release-notes.md +0 -11
  19. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/.github/workflows/release.yml +0 -0
  20. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/.gitignore +0 -0
  21. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/ACKNOWLEDGMENTS.md +0 -0
  22. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/CODE_OF_CONDUCT.md +0 -0
  23. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/CONTRIBUTING.md +0 -0
  24. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/LICENSE +0 -0
  25. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/README.md +0 -0
  26. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/ROADMAP.md +0 -0
  27. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/SECURITY.md +0 -0
  28. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/README.md +0 -0
  29. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
  30. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
  31. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
  32. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
  33. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
  34. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
  35. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
  36. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/adr/README.md +0 -0
  37. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/api.md +0 -0
  38. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/architecture.md +0 -0
  39. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/artifacts.md +0 -0
  40. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/README.md +0 -0
  41. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/001_runtime_kernel.md +0 -0
  42. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
  43. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
  44. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
  45. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
  46. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
  47. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
  48. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
  49. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/003_wait_primitives.md +0 -0
  50. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
  51. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
  52. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
  53. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
  54. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/004_scheduler_driver.md +0 -0
  55. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
  56. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
  57. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
  58. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/009_artifact_store.md +0 -0
  59. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/010_examples_and_composition.md +0 -0
  60. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/011_subworkflow_support.md +0 -0
  61. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
  62. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
  63. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
  64. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
  65. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
  66. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
  67. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
  68. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
  69. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
  70. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
  71. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
  72. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
  73. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
  74. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
  75. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
  76. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
  77. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
  78. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
  79. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
  80. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
  81. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
  82. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
  83. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
  84. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/004_tests.md +0 -0
  85. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/005_docs_updates.md +0 -0
  86. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
  87. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
  88. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
  89. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/README.md +0 -0
  90. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
  91. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
  92. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
  93. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
  94. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
  95. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
  96. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
  97. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
  98. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
  99. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
  100. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
  101. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
  102. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
  103. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
  104. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
  105. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_portability/README.md +0 -0
  106. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
  107. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
  108. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
  109. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
  110. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
  111. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
  112. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
  113. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
  114. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
  115. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
  116. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
  117. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
  118. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
  119. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
  120. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
  121. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
  122. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
  123. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
  124. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
  125. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
  126. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
  127. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
  128. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
  129. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
  130. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
  131. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
  132. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
  133. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
  134. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
  135. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/email.md +0 -0
  136. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/entity-runtime.md +0 -0
  137. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/evidence.md +0 -0
  138. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/faq.md +0 -0
  139. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/getting-started.md +0 -0
  140. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/integrations/abstractcore.md +0 -0
  141. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/limits.md +0 -0
  142. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/manual_testing.md +0 -0
  143. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/mcp-worker.md +0 -0
  144. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/proposal.md +0 -0
  145. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/provenance.md +0 -0
  146. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/snapshots.md +0 -0
  147. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/tool-approval.md +0 -0
  148. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/tools-comms.md +0 -0
  149. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/troubleshooting.md +0 -0
  150. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/docs/workflow-bundles.md +0 -0
  151. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/01_hello_world.py +0 -0
  152. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/02_ask_user.py +0 -0
  153. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/03_wait_until.py +0 -0
  154. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/04_multi_step.py +0 -0
  155. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/05_persistence.py +0 -0
  156. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/06_llm_integration.py +0 -0
  157. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/07_react_agent.py +0 -0
  158. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/examples/README.md +0 -0
  159. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/mkdocs.yml +0 -0
  160. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/pytest.ini +0 -0
  161. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/scripts/backfill_diary_edges.py +0 -0
  162. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/scripts/generate_llms_full.py +0 -0
  163. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/__init__.py +0 -0
  164. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/__init__.py +0 -0
  165. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/adapters.py +0 -0
  166. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/bundle.py +0 -0
  167. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
  168. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
  169. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/commands.py +0 -0
  170. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/ledger.py +0 -0
  171. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/automations/service.py +0 -0
  172. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/__init__.py +0 -0
  173. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/config.py +0 -0
  174. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/effect_cancellation.py +0 -0
  175. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/event_keys.py +0 -0
  176. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/health.py +0 -0
  177. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/live_deltas.py +0 -0
  178. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/models.py +0 -0
  179. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/policy.py +0 -0
  180. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/progress_channel.py +0 -0
  181. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/run_attribution.py +0 -0
  182. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/run_identity.py +0 -0
  183. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/run_lifecycle.py +0 -0
  184. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/runtime.py +0 -0
  185. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/spec.py +0 -0
  186. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/tool_scope.py +0 -0
  187. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/core/vars.py +0 -0
  188. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/documents/__init__.py +0 -0
  189. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/documents/charts.py +0 -0
  190. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/documents/docx.py +0 -0
  191. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/documents/pdf.py +0 -0
  192. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/__init__.py +0 -0
  193. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/actions.py +0 -0
  194. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/automations.py +0 -0
  195. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/binding.py +0 -0
  196. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/feeder.py +0 -0
  197. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/frame.py +0 -0
  198. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/email/inbox.py +0 -0
  199. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/evidence/__init__.py +0 -0
  200. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/evidence/recorder.py +0 -0
  201. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/history_bundle.py +0 -0
  202. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/__init__.py +0 -0
  203. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/act_only.py +0 -0
  204. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/chat.py +0 -0
  205. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/communities.py +0 -0
  206. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/diary.py +0 -0
  207. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/digest.py +0 -0
  208. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/entity_runtime.py +0 -0
  209. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/fingerprint.py +0 -0
  210. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/lease.py +0 -0
  211. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/life.py +0 -0
  212. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/memory_reader.py +0 -0
  213. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/night_voice.py +0 -0
  214. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/phase_graph.py +0 -0
  215. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/phase_spec.py +0 -0
  216. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/prelude.py +0 -0
  217. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/prompt_overlay.py +0 -0
  218. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/reflection.py +0 -0
  219. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
  220. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/substrate.py +0 -0
  221. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/tool_effects.py +0 -0
  222. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/tool_policy.py +0 -0
  223. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/tools.py +0 -0
  224. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/identity/visit_workflow.py +0 -0
  225. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/__init__.py +0 -0
  226. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/__init__.py +0 -0
  227. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
  228. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
  229. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
  230. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
  231. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
  232. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
  233. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
  234. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
  235. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +0 -0
  236. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
  237. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
  238. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
  239. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
  240. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
  241. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
  242. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
  243. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
  244. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
  245. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
  246. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
  247. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/run_facade.py +0 -0
  248. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
  249. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
  250. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
  251. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
  252. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
  253. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
  254. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +0 -0
  255. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
  256. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
  257. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
  258. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
  259. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
  260. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/__init__.py +0 -0
  261. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/active_context.py +0 -0
  262. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/active_memory.py +0 -0
  263. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/compaction.py +0 -0
  264. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/kg_packets.py +0 -0
  265. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/memact_composer.py +0 -0
  266. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/recall_levels.py +0 -0
  267. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/memory/token_budget.py +0 -0
  268. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/rendering/__init__.py +0 -0
  269. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
  270. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/rendering/json_stringify.py +0 -0
  271. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/scheduler/__init__.py +0 -0
  272. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/scheduler/convenience.py +0 -0
  273. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/scheduler/multi_store.py +0 -0
  274. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/scheduler/registry.py +0 -0
  275. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/scheduler/scheduler.py +0 -0
  276. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/session_history.py +0 -0
  277. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/session_turns.py +0 -0
  278. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/__init__.py +0 -0
  279. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/artifacts.py +0 -0
  280. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/base.py +0 -0
  281. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/commands.py +0 -0
  282. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/in_memory.py +0 -0
  283. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/json_files.py +0 -0
  284. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/lease.py +0 -0
  285. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/ledger_chain.py +0 -0
  286. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/ledger_slim.py +0 -0
  287. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/observable.py +0 -0
  288. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/offloading.py +0 -0
  289. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/serialize.py +0 -0
  290. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/snapshots.py +0 -0
  291. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/sqlite.py +0 -0
  292. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/storage/steer_sidecar.py +0 -0
  293. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/__init__.py +0 -0
  294. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/email_received.py +0 -0
  295. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/manual.py +0 -0
  296. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/protocol.py +0 -0
  297. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/registry.py +0 -0
  298. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/triggers/schedule.py +0 -0
  299. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/turn_grounding.py +0 -0
  300. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/utils/__init__.py +0 -0
  301. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/utils/atomic_files.py +0 -0
  302. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/utils/file_filters.py +0 -0
  303. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/utils/workspace_paths.py +0 -0
  304. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
  305. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
  306. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
  307. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
  308. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
  309. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
  310. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
  311. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
  312. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
  313. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
  314. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
  315. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/compiler.py +0 -0
  316. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
  317. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
  318. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
  319. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
  320. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
  321. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
  322. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/executor.py +0 -0
  323. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
  324. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
  325. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
  326. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
  327. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
  328. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/workflow_bundle/models.py +0 -0
  329. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/workflow_bundle/packer.py +0 -0
  330. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/workflow_bundle/reader.py +0 -0
  331. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/src/abstractruntime/workflow_bundle/registry.py +0 -0
  332. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/README.md +0 -0
  333. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/automation_harness.py +0 -0
  334. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/conftest.py +0 -0
  335. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/email_wp2_support.py +0 -0
  336. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/live_email/conftest.py +0 -0
  337. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/live_email/live_email_support.py +0 -0
  338. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/live_email/test_email_live_runtime.py +0 -0
  339. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_abstractcore_comms_facade.py +0 -0
  340. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_abstractcore_discovery_facade.py +0 -0
  341. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_abstractcore_host_facade.py +0 -0
  342. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_abstractcore_run_facade.py +0 -0
  343. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_abstractcore_telegram_facade.py +0 -0
  344. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_active_context_policy.py +0 -0
  345. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_active_memory.py +0 -0
  346. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_agora_agent_alias_identity.py +0 -0
  347. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_agora_tools_http.py +0 -0
  348. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_analyze_media_addressing_and_walling.py +0 -0
  349. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_answer_user_effect.py +0 -0
  350. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_artifacts.py +0 -0
  351. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_commands.py +0 -0
  352. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_controller.py +0 -0
  353. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_controller_recovery.py +0 -0
  354. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_discussion_isolation.py +0 -0
  355. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_index.py +0 -0
  356. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_next_fire.py +0 -0
  357. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_occurrence_recovery.py +0 -0
  358. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_replay_read_only.py +0 -0
  359. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_retry.py +0 -0
  360. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_session_turns.py +0 -0
  361. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_status.py +0 -0
  362. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_automation_tool_approval.py +0 -0
  363. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_browser_probe_target_walling.py +0 -0
  364. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_budget_law_no_unrequested_caps.py +0 -0
  365. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_capability_default_reasoning.py +0 -0
  366. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_chat_summarizer_integration.py +0 -0
  367. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_code_node_restricted_python.py +0 -0
  368. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_command_store.py +0 -0
  369. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_compaction_helpers.py +0 -0
  370. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_compaction_summarizer_route.py +0 -0
  371. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_config_facade_models_engines.py +0 -0
  372. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_control_adapter_while.py +0 -0
  373. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_controller_bundle_packaged.py +0 -0
  374. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_crash_ordering_inversions.py +0 -0
  375. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_create_if_absent.py +0 -0
  376. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_data_registry_facade.py +0 -0
  377. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_camera_gating.py +0 -0
  378. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_comms_gating.py +0 -0
  379. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_include_skim_files.py +0 -0
  380. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_include_skim_folders.py +0 -0
  381. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_include_skim_web.py +0 -0
  382. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_default_tools_search_files_executor.py +0 -0
  383. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_diary_capture.py +0 -0
  384. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_diary_write_rescue.py +0 -0
  385. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_directory_lease.py +0 -0
  386. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_disabled_toolsets_seam.py +0 -0
  387. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_discovery_survives_unbuildable_default.py +0 -0
  388. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_discovery_tts_unavailable_reason.py +0 -0
  389. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_discovery_voice_openai_api_key.py +0 -0
  390. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_discussion_session_anchor.py +0 -0
  391. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_document_markdown_tables.py +0 -0
  392. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_document_renderers_hr_quote.py +0 -0
  393. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_durable_toolsets.py +0 -0
  394. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_durable_write_discipline.py +0 -0
  395. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
  396. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_effect_cancellation.py +0 -0
  397. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_effect_issuance_idempotency.py +0 -0
  398. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_effect_payload_stays_json_serializable.py +0 -0
  399. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_election_consequence_teaching.py +0 -0
  400. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_binding_and_refiner.py +0 -0
  401. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_gate_fixes.py +0 -0
  402. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_inbox_and_trigger.py +0 -0
  403. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_regate_fixes.py +0 -0
  404. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_review_fixes.py +0 -0
  405. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_self_trigger_loop.py +0 -0
  406. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_email_toolset_and_walls.py +0 -0
  407. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_emergence_experiment.py +0 -0
  408. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_emit_event_uses_wait_index.py +0 -0
  409. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_emit_event_without_workflow_registry.py +0 -0
  410. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_endpoint_profile_route_context.py +0 -0
  411. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_awake_memory_fixes.py +0 -0
  412. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_brain_effects.py +0 -0
  413. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_chat_driver.py +0 -0
  414. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_chat_tools_reflection.py +0 -0
  415. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_diary.py +0 -0
  416. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_execute_tool.py +0 -0
  417. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_fetch_url_tool.py +0 -0
  418. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_history_window.py +0 -0
  419. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_life_loop.py +0 -0
  420. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_memory_richness.py +0 -0
  421. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_phase_graph_conformance.py +0 -0
  422. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_react_visit_window.py +0 -0
  423. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_recent_memories.py +0 -0
  424. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_runtime.py +0 -0
  425. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_search_memory.py +0 -0
  426. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
  427. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_substrate_resolution.py +0 -0
  428. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_visit_honesty.py +0 -0
  429. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_workspace_cap.py +0 -0
  430. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_entity_workspace_tools.py +0 -0
  431. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_event_wait_index.py +0 -0
  432. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
  433. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_evidence_recorder.py +0 -0
  434. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
  435. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_execute_command_output_offload.py +0 -0
  436. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_execution_capability_discovery.py +0 -0
  437. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_explicit_eject_other_clients.py +0 -0
  438. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_factory_default_retry_policy.py +0 -0
  439. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
  440. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_format_repair_nudge.py +0 -0
  441. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_fresh_install_no_provider.py +0 -0
  442. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_gateway_facades_c4899.py +0 -0
  443. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_git_read_only_refiner.py +0 -0
  444. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_hf_process_residency_merge.py +0 -0
  445. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_history_window_multimodal.py +0 -0
  446. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_hot_path_store_reads.py +0 -0
  447. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_indexed_idempotency_lookup.py +0 -0
  448. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_integration_abstractcore.py +0 -0
  449. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_integrations_abstractcore.py +0 -0
  450. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_json_file_run_store_children_index.py +0 -0
  451. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_json_run_cache_bound.py +0 -0
  452. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_json_store_scan_memo.py +0 -0
  453. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_jsonl_ledger_recovery.py +0 -0
  454. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_kg_learn_and_recall_contract.py +0 -0
  455. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_ledger_chain.py +0 -0
  456. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_ledger_record_slimming.py +0 -0
  457. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_ledger_subscription.py +0 -0
  458. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_live_token_deltas.py +0 -0
  459. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_media_artifact_refs.py +0 -0
  460. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
  461. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
  462. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_payload_shape_refusal.py +0 -0
  463. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_requires_prompt.py +0 -0
  464. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_response_schema_normalization.py +0 -0
  465. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_structured_output_fallback.py +0 -0
  466. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_text_phase_progress.py +0 -0
  467. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_truncation_retry_contract.py +0 -0
  468. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_use_context_appends_turn.py +0 -0
  469. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
  470. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_client_grounding_tail.py +0 -0
  471. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_client_media_artifacts.py +0 -0
  472. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_client_system_context.py +0 -0
  473. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_client_tool_call_parsing.py +0 -0
  474. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_retry_classification.py +0 -0
  475. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_llm_streaming_on_token.py +0 -0
  476. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_local_helper_tool_exposure.py +0 -0
  477. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_local_residency_host_sweep.py +0 -0
  478. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
  479. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_max_iterations_ceiling.py +0 -0
  480. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mcp_remote_tool_executor.py +0 -0
  481. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mcp_worker_logging.py +0 -0
  482. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mcp_worker_security.py +0 -0
  483. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mcp_worker_stdio.py +0 -0
  484. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_media_artifact_resolution.py +0 -0
  485. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_media_capability_default_routing.py +0 -0
  486. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_media_only_requests_skip_text_client.py +0 -0
  487. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_media_subprocess.py +0 -0
  488. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memact_composer_from_kg_result.py +0 -0
  489. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_appraise_handler.py +0 -0
  490. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_communities.py +0 -0
  491. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
  492. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_packets.py +0 -0
  493. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_predicate_aliasing.py +0 -0
  494. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_query_packetization_restart.py +0 -0
  495. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
  496. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
  497. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_note_effect.py +0 -0
  498. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_query_effect.py +0 -0
  499. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_query_rich_filters.py +0 -0
  500. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
  501. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_seam_handlers.py +0 -0
  502. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_seam_sqlite_durability.py +0 -0
  503. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_memory_tag_effect.py +0 -0
  504. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mlx_generation_serialization.py +0 -0
  505. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_mlx_process_residency_merge.py +0 -0
  506. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_model_eject_cancel.py +0 -0
  507. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_model_residency_clean_switch.py +0 -0
  508. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_model_residency_control_plane.py +0 -0
  509. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
  510. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_multi_store_scheduler.py +0 -0
  511. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_multimodal_abstractcore_integration.py +0 -0
  512. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_native_mlx_application_wiring.py +0 -0
  513. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_native_mlx_execution_controls_live.py +0 -0
  514. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_native_tool_channel.py +0 -0
  515. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_night_voice.py +0 -0
  516. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_no_default_provider_refusal_ux.py +0 -0
  517. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_offload_answer_chain_c4978.py +0 -0
  518. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
  519. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_offloading.py +0 -0
  520. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_packaging_extras.py +0 -0
  521. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_parallel_readonly_tool_execution.py +0 -0
  522. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_pause_resume.py +0 -0
  523. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_pdf_unicode_rendering.py +0 -0
  524. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_personal_cycle.py +0 -0
  525. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_phantom_attachment_index.py +0 -0
  526. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_phase_graph_artifact_control.py +0 -0
  527. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_phase_graph_obedience.py +0 -0
  528. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_phase_vocabulary_migration.py +0 -0
  529. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
  530. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_cache_export_import.py +0 -0
  531. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
  532. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_cache_modules.py +0 -0
  533. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_cache_posture_inheritance.py +0 -0
  534. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
  535. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_prompt_overlay.py +0 -0
  536. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_provider_endpoint_profile_resolution.py +0 -0
  537. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_provider_pin_routing_isolation.py +0 -0
  538. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_queryable_run_store.py +0 -0
  539. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
  540. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_read_idle_threading.py +0 -0
  541. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_readoption_experiment.py +0 -0
  542. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_real_integration.py +0 -0
  543. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_realize_election.py +0 -0
  544. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_recall_levels_policy.py +0 -0
  545. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_remote_client_cancel.py +0 -0
  546. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_remote_llm_client.py +0 -0
  547. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_remote_speculation_defaults.py +0 -0
  548. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_rendering_agent_trace_report.py +0 -0
  549. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_rendering_json_stringify.py +0 -0
  550. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_report_branding.py +0 -0
  551. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_resident_media_generation.py +0 -0
  552. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_resume_concurrent_same_wait.py +0 -0
  553. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_retry_idempotency.py +0 -0
  554. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_run_history_bundle.py +0 -0
  555. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_run_index_workspace_root.py +0 -0
  556. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_run_mutation_lock.py +0 -0
  557. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_run_scoped_tool_policy.py +0 -0
  558. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_run_tool_scope_ceiling.py +0 -0
  559. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_browser_session_boundary.py +0 -0
  560. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
  561. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_default_provider_model_refresh.py +0 -0
  562. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_effect_invocation_trace.py +0 -0
  563. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_health_and_bounded_vars.py +0 -0
  564. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_install_boundary.py +0 -0
  565. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
  566. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_node_traces.py +0 -0
  567. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_start_seeds_tool_support.py +0 -0
  568. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_runtime_tick_step_gate.py +0 -0
  569. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_scheduler.py +0 -0
  570. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_send_email_refiner.py +0 -0
  571. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_send_email_self_default_policy.py +0 -0
  572. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
  573. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_history.py +0 -0
  574. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_prompt_cache_attribution.py +0 -0
  575. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_prompt_cache_visibility.py +0 -0
  576. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_route_stamp.py +0 -0
  577. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_session_start_cost.py +0 -0
  578. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_shell_tool_exposure.py +0 -0
  579. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_snapshots.py +0 -0
  580. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_speculation_inheritance.py +0 -0
  581. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_speculation_reaches_provider_construction.py +0 -0
  582. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_sqlite_ledger_store.py +0 -0
  583. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_start_subworkflow_async_wait.py +0 -0
  584. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
  585. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
  586. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_steer_sidecar.py +0 -0
  587. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_storage_deletion.py +0 -0
  588. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_structured_output_schema_enum.py +0 -0
  589. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_subworkflow.py +0 -0
  590. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_terminal_effect_completion.py +0 -0
  591. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
  592. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_thinking_inheritance.py +0 -0
  593. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
  594. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_approval_executor.py +0 -0
  595. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_approval_resume_executes.py +0 -0
  596. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_approval_wait_key_identity.py +0 -0
  597. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_calls_idempotency_keys.py +0 -0
  598. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_catalog.py +0 -0
  599. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_descriptor_registry.py +0 -0
  600. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_argument_sanitization.py +0 -0
  601. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_error_output_detection.py +0 -0
  602. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_filename_alias.py +0 -0
  603. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
  604. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_read_file_aliases.py +0 -0
  605. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_executor_timeout.py +0 -0
  606. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_inventory_facade.py +0 -0
  607. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_invoke_effect.py +0 -0
  608. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_policy_and_mounts.py +0 -0
  609. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_tool_wait_allowlist_safety.py +0 -0
  610. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_topic_election_world_model.py +0 -0
  611. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_trace_context_propagation.py +0 -0
  612. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_trigger_registry.py +0 -0
  613. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_trigger_schedule_math.py +0 -0
  614. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_turn_grounding_byte_stability.py +0 -0
  615. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_turn_grounding_carriers_a3.py +0 -0
  616. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_vars_query_effect.py +0 -0
  617. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visit_ab_fixture.py +0 -0
  618. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visit_midturn_elections.py +0 -0
  619. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visit_midturn_resume.py +0 -0
  620. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visit_workflow.py +0 -0
  621. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
  622. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
  623. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
  624. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
  625. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
  626. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
  627. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_entity_memory_nodes.py +0 -0
  628. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
  629. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_llm_call_partial_override.py +0 -0
  630. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
  631. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_memact_compose_node.py +0 -0
  632. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
  633. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
  634. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
  635. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_unknown_node_type_refuses.py +0 -0
  636. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
  637. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_add_message_builtin.py +0 -0
  638. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
  639. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_agora_react_agent.py +0 -0
  640. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_call_tool_node.py +0 -0
  641. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
  642. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_compiler_basic.py +0 -0
  643. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
  644. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_continue_on_error.py +0 -0
  645. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_edit_json_schema_node.py +0 -0
  646. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
  647. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_file_nodes_workspace.py +0 -0
  648. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_function_library.py +0 -0
  649. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_get_element_node.py +0 -0
  650. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_get_random_element_node.py +0 -0
  651. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_get_var_node.py +0 -0
  652. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_has_tools_builtin.py +0 -0
  653. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
  654. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
  655. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_make_object_node.py +0 -0
  656. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_media_nodes.py +0 -0
  657. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_memory_effect_nodes.py +0 -0
  658. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_memory_source_pins.py +0 -0
  659. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_pin_expressions.py +0 -0
  660. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_prompt_only.py +0 -0
  661. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_random_nodes.py +0 -0
  662. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_schema_enum_switch.py +0 -0
  663. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_string_contains_replace.py +0 -0
  664. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_visualflow_tool_parameters_node.py +0 -0
  665. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_voice_openai_api_key_path.py +0 -0
  666. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_w4_feelings_lens.py +0 -0
  667. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_wait_event_deadline.py +0 -0
  668. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_wait_event_prompt_metadata.py +0 -0
  669. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_wait_until_streak.py +0 -0
  670. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_wait_until_utc_normalization.py +0 -0
  671. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workflow_bundle_registry.py +0 -0
  672. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_builtin_deny.py +0 -0
  673. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
  674. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_policy_allowlist_mode.py +0 -0
  675. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
  676. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
  677. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_prompt_context.py +0 -0
  678. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_workspace_read_only.py +0 -0
  679. {abstractruntime-0.8.2 → abstractruntime-0.8.4}/tests/test_write_chart.py +0 -0
@@ -60,6 +60,7 @@ jobs:
60
60
  tests/test_abstractcore_comms_facade.py \
61
61
  tests/test_abstractcore_discovery_facade.py \
62
62
  tests/test_automation_definition.py \
63
+ tests/test_automation_email_results.py \
63
64
  tests/test_automation_tool_approval.py \
64
65
  tests/test_default_tools_comms_gating.py \
65
66
  tests/test_every_path_bearing_tool_is_walled.py \
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ Nothing yet.
11
+
12
+ ## [0.8.4] - 2026-10-02
13
+
14
+ - Automations accept `context.growing.max_tokens` at creation and revision, defaulting to 50,000 tokens. Whole-turn history and admitted retry inputs are preserved.
15
+ - Email-enabled automations produce a result notification for every completed occurrence, with the full answer and configurable `notify.recipients`.
16
+
17
+ ## [0.8.3] - 2026-10-01
18
+
19
+
20
+ ### Added
21
+
22
+ - `integrations.abstractcore.mcp_facade`: opens a stdio or HTTP MCP client (a stdio server starts
23
+ with exactly the environment given), turns a server's tool into an `mcp::<server>::<tool>` spec
24
+ without its URL, and runs `tools/call` with the runtime's result mapping. The gateway calls
25
+ registered MCP servers through it.
26
+
27
+ ### Changed
28
+
29
+ - An automation run started by an email from someone else (untrusted input) is never offered an MCP
30
+ tool: every `mcp::...` name leaves its tool lists and is never granted, even when named.
31
+
10
32
  ## [0.8.2] - 2026-10-01
11
33
 
12
34
  Pausing an automation also stops its retries. Requires AbstractCore 2.20.2 (unchanged).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: AbstractRuntime
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: AbstractRuntime: a durable graph runner designed to pair with AbstractCore.
5
5
  Project-URL: AbstractCore (website), https://www.abstractcore.ai/
6
6
  Project-URL: AbstractRuntime (GitHub), https://github.com/lpalbou/abstractruntime
@@ -318,7 +318,7 @@ controller is woken with `max_steps=0`; the host (or `drive_automation`) then ti
318
318
  | | Independent (default) | Growing |
319
319
  |---|---|---|
320
320
  | Session | a new session per occurrence, named after its attempt-1 run id | the automation's session, `automation:<automation_id>` |
321
- | History given to the occurrence | none | the automation's previous turns as `input_data.context.messages`: the most recent 50,000 tokens of whole turns (the session history window) |
321
+ | History given to the occurrence | none | the automation's previous turns as `input_data.context.messages`: the most recent whole turns within the configured token budget (50,000 tokens by default) (the session history window) |
322
322
  | `use_context` given to the target | `false` | `true` |
323
323
  | `_meta.occurrence.session_kind` | `occurrence` | `automation` |
324
324
 
@@ -514,7 +514,7 @@ Automations are **quiet by default**. An occurrence creates an attention item on
514
514
  - its output carries `notify: true`: the item's title is the automation title and its body is the answer, cut to 280
515
515
  characters;
516
516
  - its output carries `notify: {title, body}`: title at most 120 characters (the automation title when empty), body at
517
- most 2,000 characters. A missing, `false` or empty `notify` stays quiet;
517
+ most 2,000 characters. A missing, `false` or empty `notify` stays quiet unless result email is enabled;
518
518
  - it **failed after its last retry**: the title is "<automation title> failed" and the body is the error. A failure
519
519
  that a retry fixed is quiet, and so is a cancelled occurrence.
520
520
 
@@ -523,7 +523,7 @@ with its end-node values or `{success, result}`. An output with `success: false`
523
523
  must flag a result adds `notify` next to its answer.
524
524
 
525
525
  Each notify or final failure creates exactly one attention item per occurrence. The item is carried by the The item's `channels` repeats the definition's `notify.channels`; a host that delivers notifications by email
526
- mails the owner when `email` is listed.
526
+ emails every completed result when `email` is listed. `notify.recipients` selects delivery addresses (default `["self"]`); the full answer is retained for email while console previews stay bounded.
527
527
  occurrence's `automation.completed` record with a per-automation sequence number.
528
528
 
529
529
  `list_attention(ledger_store, automation_id, *, after_seq=0, cursor=None, limit=50)` returns
@@ -685,7 +685,7 @@ receives its result directly.
685
685
  event source yet.
686
686
  - Occurrences run one at a time (`serial`), missed ticks coalesce, and a failed occurrence never stops the
687
687
  automation (`failure: "continue"`). These policies cannot be changed.
688
- - Growing history is the most recent 50,000 tokens of whole turns and is not summarized automatically; older turns
688
+ - Growing history is the most recent whole turns within the configured token budget (50,000 tokens by default) and is not summarized automatically; older turns
689
689
  drop out of the replay (they stay in the store).
690
690
  - Tools outside `TOOL_EFFECT_CLASSES`, such as third-party MCP tools, still ask for approval under `auto`.
691
691
  - Retries repeat external effects.
@@ -701,3 +701,14 @@ receives its result directly.
701
701
  - [email.md](email.md): email accounts, the `email.received@1` trigger and the send-email action
702
702
  - [faq.md](faq.md): common questions
703
703
  - [troubleshooting.md](troubleshooting.md#an-automation-does-not-fire): symptom-oriented fixes
704
+
705
+ ## Growing context limit
706
+
707
+ Choose **Growing** to set **Max growing context (tokens)** when creating or editing an
708
+ automation. The default is 50,000; enter `30000` for a 30,000-token history budget.
709
+ The limit is hidden for **Independent** runs. Changing it affects subsequent occurrences;
710
+ already admitted occurrences retain their history for retries. History retains whole turns,
711
+ including the newest turn even when that turn alone exceeds the budget.
712
+
713
+ The API field is `context.growing.max_tokens`, a positive integer. Existing definitions
714
+ that omit it retain the 50,000-token default.
@@ -3839,7 +3839,7 @@ controller is woken with `max_steps=0`; the host (or `drive_automation`) then ti
3839
3839
  | | Independent (default) | Growing |
3840
3840
  |---|---|---|
3841
3841
  | Session | a new session per occurrence, named after its attempt-1 run id | the automation's session, `automation:<automation_id>` |
3842
- | History given to the occurrence | none | the automation's previous turns as `input_data.context.messages`: the most recent 50,000 tokens of whole turns (the session history window) |
3842
+ | History given to the occurrence | none | the automation's previous turns as `input_data.context.messages`: the most recent whole turns within the configured token budget (50,000 tokens by default) (the session history window) |
3843
3843
  | `use_context` given to the target | `false` | `true` |
3844
3844
  | `_meta.occurrence.session_kind` | `occurrence` | `automation` |
3845
3845
 
@@ -4035,7 +4035,7 @@ Automations are **quiet by default**. An occurrence creates an attention item on
4035
4035
  - its output carries `notify: true`: the item's title is the automation title and its body is the answer, cut to 280
4036
4036
  characters;
4037
4037
  - its output carries `notify: {title, body}`: title at most 120 characters (the automation title when empty), body at
4038
- most 2,000 characters. A missing, `false` or empty `notify` stays quiet;
4038
+ most 2,000 characters. A missing, `false` or empty `notify` stays quiet unless result email is enabled;
4039
4039
  - it **failed after its last retry**: the title is "<automation title> failed" and the body is the error. A failure
4040
4040
  that a retry fixed is quiet, and so is a cancelled occurrence.
4041
4041
 
@@ -4044,7 +4044,7 @@ with its end-node values or `{success, result}`. An output with `success: false`
4044
4044
  must flag a result adds `notify` next to its answer.
4045
4045
 
4046
4046
  Each notify or final failure creates exactly one attention item per occurrence. The item is carried by the The item's `channels` repeats the definition's `notify.channels`; a host that delivers notifications by email
4047
- mails the owner when `email` is listed.
4047
+ emails every completed result when `email` is listed. `notify.recipients` selects delivery addresses (default `["self"]`); the full answer is retained for email while console previews stay bounded.
4048
4048
  occurrence's `automation.completed` record with a per-automation sequence number.
4049
4049
 
4050
4050
  `list_attention(ledger_store, automation_id, *, after_seq=0, cursor=None, limit=50)` returns
@@ -4206,7 +4206,7 @@ receives its result directly.
4206
4206
  event source yet.
4207
4207
  - Occurrences run one at a time (`serial`), missed ticks coalesce, and a failed occurrence never stops the
4208
4208
  automation (`failure: "continue"`). These policies cannot be changed.
4209
- - Growing history is the most recent 50,000 tokens of whole turns and is not summarized automatically; older turns
4209
+ - Growing history is the most recent whole turns within the configured token budget (50,000 tokens by default) and is not summarized automatically; older turns
4210
4210
  drop out of the replay (they stay in the store).
4211
4211
  - Tools outside `TOOL_EFFECT_CLASSES`, such as third-party MCP tools, still ask for approval under `auto`.
4212
4212
  - Retries repeat external effects.
@@ -4223,6 +4223,17 @@ receives its result directly.
4223
4223
  - [faq.md](faq.md): common questions
4224
4224
  - [troubleshooting.md](troubleshooting.md#an-automation-does-not-fire): symptom-oriented fixes
4225
4225
 
4226
+ ## Growing context limit
4227
+
4228
+ Choose **Growing** to set **Max growing context (tokens)** when creating or editing an
4229
+ automation. The default is 50,000; enter `30000` for a 30,000-token history budget.
4230
+ The limit is hidden for **Independent** runs. Changing it affects subsequent occurrences;
4231
+ already admitted occurrences retain their history for retries. History retains whole turns,
4232
+ including the newest turn even when that turn alone exceeds the budget.
4233
+
4234
+ The API field is `context.growing.max_tokens`, a positive integer. Existing definitions
4235
+ that omit it retain the 50,000-token default.
4236
+
4226
4237
 
4227
4238
  ==============================================================================
4228
4239
  # FILE: docs/tool-approval.md
@@ -57,7 +57,7 @@
57
57
  - [MCP worker](docs/mcp-worker.md): `abstractruntime-mcp-worker` CLI (stdio/HTTP)
58
58
  - [Comms toolset](docs/tools-comms.md): email enabled by the host (`email_enabled=True`, no env flag); WhatsApp/Telegram env gating
59
59
  - [Email](docs/email.md): one user, one runtime, one mailbox: `_runtime.email_account` binding resolved at call time through `Runtime.set_email_context_resolver` (credentials never in vars, ledger or results), `send_email_recipient@v2` (unattended only to self or to the definition's `policy.email_allowed_recipients`), the resolver's `use` (`agent_tool` / `action`) so a host's agent-tools switch gates agent tools only, large structured tool outputs offloaded to attachments, durable event inbox (`JsonFileEventInbox`, retention 90 days / 10,000 events via `prune_email_inbox`) filled by `EmailInboxFeeder.poll` (read-only, per-message cursor, UIDVALIDITY resync, typed failures with backoff), the `email.received@1` trigger (typed filters, batches every `every`, each message once, untrusted input: messages and framed prompt stored as artifacts (refs only in the controller's records), frame markers with a per-occurrence random boundary, and "allow all tools" granting by kind only (no network egress beyond configured services, no execution, no messaging, no writes outside the workspace (the memory-writing tools included), no delegation; anything else only when named in `policy.untrusted_input_tools`, sending tools never; under "ask" nothing runs unasked but the named tools, and the executor's static defaults never decide for an untrusted run or its children)) and the send-email action (fixed-placeholder templates)
60
- - [Automations](docs/automations.md): an automation is a durable controller run that starts its target as deterministic child runs (occurrences) on `schedule@1` (fixed UTC intervals, coalesced missed ticks) or `manual@1`; `create_automation`, `apply_automation_command` (pause, resume, run_now, revise, stop_current, archive; idempotent per `command_id`), independent or growing context, `start_discussion` (fork at any occurrence N, seeded with the timeline 1..N, own writable workspace, the automation's workspace mounted read-only via `_runtime.workspace_read_only_paths`: file writes refused inside, reads and commands allowed), `policy.tool_approval` (`auto` or `ask`), `policy.email_allowed_recipients`, `notify.channels`, the `email.received@1` trigger, typed `pending_waits`, `notify` attention items and retries; storage guarantees: `create_if_absent`, `run_mutation_lock`, turn roots and `session_kind` in the run index, one writer process per store, `Runtime.start` refusing session starts it cannot attribute
60
+ - [Automations](docs/automations.md): configurable growing-context budgets and result email; an automation is a durable controller run that starts its target as deterministic child runs (occurrences) on `schedule@1` (fixed UTC intervals, coalesced missed ticks) or `manual@1`; `create_automation`, `apply_automation_command` (pause, resume, run_now, revise, stop_current, archive; idempotent per `command_id`), independent or growing context, `start_discussion` (fork at any occurrence N, seeded with the timeline 1..N, own writable workspace, the automation's workspace mounted read-only via `_runtime.workspace_read_only_paths`: file writes refused inside, reads and commands allowed), `policy.tool_approval` (`auto` or `ask`), `policy.email_allowed_recipients`, `notify.channels`, the `email.received@1` trigger, typed `pending_waits`, `notify` attention items and retries; storage guarantees: `create_if_absent`, `run_mutation_lock`, turn roots and `session_kind` in the run index, one writer process per store, `Runtime.start` refusing session starts it cannot attribute
61
61
  - [Tool approval](docs/tool-approval.md): tool risk tiers, the run-policy rank ceiling, and per-call refiners
62
62
  - [Entity runtime](docs/entity-runtime.md): per-entity runtimes, homes, the one-writer lease, act-only diary privacy, and durable visit waits
63
63
  - [Models, engines and host jobs](docs/integrations/abstractcore.md#models-engines-and-host-jobs-config-facade): `config_facade` passthroughs for hosts; `host_job_cancel(job_id, *, by="api", user=None)` records who cancelled a job
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "AbstractRuntime"
7
- version = "0.8.2"
7
+ version = "0.8.4"
8
8
  description = "AbstractRuntime: a durable graph runner designed to pair with AbstractCore."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,2 @@
1
+ - Automations accept `context.growing.max_tokens` at creation and revision, defaulting to 50,000 tokens. Whole-turn history and admitted retry inputs are preserved.
2
+ - Email-enabled automations produce a result notification for every completed occurrence, with the full answer and configurable `notify.recipients`.
@@ -23,6 +23,7 @@ from .automations.controller import current_occurrence as _current_occurrence
23
23
  from .automations.controller import next_fire_at as _next_fire_at
24
24
  from .automations.models import AUTOMATION_STATUSES, automation_status
25
25
  from .core.models import RunState, RunStatus, WaitReason
26
+ from .session_history import HISTORY_REPLAY_MAX_TOKENS
26
27
 
27
28
  # Upper bound for one automation's index scan (occurrence rows, controllers).
28
29
  # Rows are column-only and cheap; a bound keeps a runaway store from turning a
@@ -116,6 +117,7 @@ def automation_summary(controller: RunState) -> Dict[str, Any]:
116
117
  "revision": definition.get("revision"),
117
118
  "trigger": definition.get("trigger"),
118
119
  "context_mode": context.get("mode", "independent"),
120
+ "growing_max_tokens": context.get("growing", {}).get("max_tokens", HISTORY_REPLAY_MAX_TOKENS),
119
121
  "target": definition.get("target"),
120
122
  "session_id": controller.session_id,
121
123
  "workspace_root": definition.get("workspace_root"),
@@ -289,6 +289,9 @@ def list_attention(
289
289
  item["body"] = att["body"]
290
290
  # Delivery channels (definition schema v2 `notify.channels`; absent on older records).
291
291
  item["channels"] = list(att.get("channels") or ["console"])
292
+ if "email_result" in att:
293
+ item["email_result"] = att["email_result"]
294
+ item["recipients"] = list(att.get("recipients") or ["self"])
292
295
  items.append(item)
293
296
  items.sort(key=lambda it: it["seq"])
294
297
  page = items[:limit]
@@ -320,7 +320,17 @@ def _never_granted(name: str) -> bool:
320
320
  `send` network reach (`agora_post_message`, `agora_send_dm`, which have no core row)."""
321
321
  from ..integrations.abstractcore.tool_effects import sends_messages
322
322
 
323
- return _grant_excludes(name) or sends_messages(name)
323
+ return _grant_excludes(name) or sends_messages(name) or _is_mcp_tool(name)
324
+
325
+
326
+ # Tools of registered MCP servers (`mcp::<server>::<tool>`, AbstractCore's naming): external
327
+ # programs whose effects no fact table here describes. A run that reads text written by other
328
+ # people is never offered one and never granted one, named or not.
329
+ _MCP_TOOL_PREFIX = "mcp::"
330
+
331
+
332
+ def _is_mcp_tool(name: Any) -> bool:
333
+ return str(name or "").strip().startswith(_MCP_TOOL_PREFIX)
324
334
 
325
335
 
326
336
  # `_runtime.untrusted_input = True`: the run reads text written by other people (an inbound
@@ -368,12 +378,13 @@ def grant_tool_approval(
368
378
  beyond configured services, no code or command execution, no messaging, no
369
379
  writes outside the run's workspace, no delegation). Every other tool
370
380
  (`fetch_url`, `skim_url`, `web_search`, `execute_command`, `shell_exec`,
371
- `execute_python`, `delegate_agent`, `channel_fs_write`, MCP tools...) is
381
+ `execute_python`, `delegate_agent`, `channel_fs_write`...) is
372
382
  granted only when the user NAMED it individually in the definition
373
383
  (`policy.untrusted_input_tools`, passed as `named_tools`), and only within
374
384
  the target's tool ceiling. Message-sending tools (`send_email`,
375
385
  `reply_email`, `agora_post_message`, `agora_send_dm`, ...) are never
376
- granted, named or not. A withheld call asks a person. Schedule and manual
386
+ granted, named or not. MCP tools (`mcp::<server>::<tool>`) leave the run's tool lists
387
+ and are never granted. A withheld call asks a person. Schedule and manual
377
388
  automations keep the full grant (decision recorded in 0992).
378
389
 
379
390
  Untrusted input under `approval="ask"` (framework backlog 0992 re-gate): the
@@ -397,6 +408,15 @@ def grant_tool_approval(
397
408
  if not untrusted_input:
398
409
  return
399
410
  replaced_target_policy = True
411
+ mcp_withheld: list = []
412
+ if untrusted_input:
413
+ # Untrusted input: every MCP tool leaves the run's tool lists (the agent's `tools` input and
414
+ # the `_runtime.allowed_tools` ceiling), so the model is never offered one.
415
+ for holder, key in ((input_data, "tools"), (runtime_ns, "allowed_tools")):
416
+ raw = holder.get(key)
417
+ if isinstance(raw, list) and any(_is_mcp_tool(t) for t in raw):
418
+ mcp_withheld += [str(t).strip() for t in raw if _is_mcp_tool(t)]
419
+ holder[key] = [t for t in raw if not _is_mcp_tool(t)]
400
420
  allowed = runtime_ns.get("allowed_tools")
401
421
  names = allowed if isinstance(allowed, list) else list(TOOL_EFFECT_CLASSES)
402
422
  candidates = sorted({n.strip() for n in names if isinstance(n, str) and n.strip()})
@@ -413,6 +433,7 @@ def grant_tool_approval(
413
433
  else:
414
434
  withheld = [n for n in candidates if _grant_excludes(n)]
415
435
  tools = [n for n in candidates if n not in withheld]
436
+ withheld = withheld + sorted(set(mcp_withheld) - set(withheld))
416
437
  policy: Dict[str, Any] = {"auto_approve_tools": tools, "withheld_tools": withheld, "source": AUTOMATION_GRANT_SOURCE}
417
438
  if untrusted_input:
418
439
  policy.update(
@@ -516,7 +537,7 @@ def build_prepared(
516
537
  )
517
538
  apply_context_mode(input_data, mode=definition["context"]["mode"])
518
539
  if definition["context"]["mode"] == "growing":
519
- from ..session_history import session_chat_messages
540
+ from ..session_history import HISTORY_REPLAY_MAX_TOKENS, session_chat_messages
520
541
 
521
542
  messages = session_chat_messages(
522
543
  run_store=turn.run_store,
@@ -524,6 +545,7 @@ def build_prepared(
524
545
  artifact_store=turn.artifact_store,
525
546
  session_id=definition["session_id"],
526
547
  automation_id=turn.automation_id,
548
+ max_tokens=definition["context"].get("growing", {}).get("max_tokens", HISTORY_REPLAY_MAX_TOKENS),
527
549
  strict=True,
528
550
  )
529
551
  context = input_data.get("context") if isinstance(input_data.get("context"), dict) else {}
@@ -788,8 +810,10 @@ def complete_occurrence(turn: Turn, *, status: str, outcome: Optional[Dict[str,
788
810
  attention = None
789
811
  notify = None
790
812
  seq = int(state.get("attention_seq") or 0)
813
+ delivery = definition_notify(definition)
814
+ email_result = "email" in delivery["channels"] and status == "completed"
791
815
  if status == "completed" and outcome is not None:
792
- notify = notify_payload(outcome.get("notify"), title=definition["title"], answer=outcome.get("answer") or "")
816
+ notify = notify_payload(True if email_result else outcome.get("notify"), title=definition["title"], answer=outcome.get("answer") or "")
793
817
  if notify is not None:
794
818
  seq += 1
795
819
  attention = {"kind": "notify", "seq": seq, **notify}
@@ -800,7 +824,10 @@ def complete_occurrence(turn: Turn, *, status: str, outcome: Optional[Dict[str,
800
824
  if attention is not None:
801
825
  # Where the item is delivered (schema v2 `notify.channels`): "email" asks the host's
802
826
  # notification dispatcher to mail the owner (framework backlog 0992 B5/C5).
803
- attention["channels"] = list(definition_notify(definition)["channels"])
827
+ attention["channels"] = list(delivery["channels"])
828
+ if email_result:
829
+ attention["email_result"] = str((outcome or {}).get("answer") or "")
830
+ attention["recipients"] = list(delivery.get("recipients", ["self"]))
804
831
  last_outcome = {
805
832
  "run_id": pending["run_id"],
806
833
  "index": int(pending["index"]),
@@ -254,14 +254,18 @@ def validate_context(value: Any) -> Dict[str, Any]:
254
254
  if mode not in CONTEXT_MODES:
255
255
  raise _invalid(f"context.mode must be one of {list(CONTEXT_MODES)}", "context.mode")
256
256
  growing = _require_mapping(ctx.get("growing", {}), "context.growing")
257
- _reject_unknown(growing, ("summary",), "context.growing")
257
+ _reject_unknown(growing, ("summary", "max_tokens"), "context.growing")
258
258
  if "summary" in growing:
259
259
  raise _invalid(
260
260
  "automatic growing-mode summaries are not supported in v1",
261
261
  "context.growing.summary",
262
262
  reason_code="unsupported_feature",
263
263
  )
264
- return {"mode": mode, "growing": {}}
264
+ if "max_tokens" in growing:
265
+ limit = growing["max_tokens"]
266
+ if isinstance(limit, bool) or not isinstance(limit, int) or limit <= 0:
267
+ raise _invalid("Max growing context must be a positive whole number of tokens", "context.growing.max_tokens")
268
+ return {"mode": mode, "growing": dict(growing)}
265
269
 
266
270
 
267
271
  def _duration(value: Any, field: str) -> str:
@@ -272,13 +276,12 @@ def _duration(value: Any, field: str) -> str:
272
276
  return value
273
277
 
274
278
 
275
- def validate_email_allowed_recipients(value: Any) -> list:
279
+ def validate_email_allowed_recipients(value: Any, *, field: str = "policy.email_allowed_recipients") -> list:
276
280
  """`["self" | "name@example.test", ...]`, lower-cased and de-duplicated (order kept).
277
281
 
278
282
  Exact addresses only: no display names, groups, domains or patterns (a pre-authorisation
279
283
  must name the person). Empty list = nobody, not even self, runs unattended.
280
284
  """
281
- field = "policy.email_allowed_recipients"
282
285
  if not isinstance(value, list):
283
286
  raise _invalid(f"{field} must be a list of 'self' or email addresses", field)
284
287
  if len(value) > MAX_EMAIL_ALLOWED_RECIPIENTS:
@@ -332,7 +335,7 @@ def validate_notify(value: Any) -> Dict[str, Any]:
332
335
  dispatcher mails the owner's registered address).
333
336
  """
334
337
  notify = _require_mapping(value if value is not None else {}, "notify")
335
- _reject_unknown(notify, ("channels",), "notify")
338
+ _reject_unknown(notify, ("channels", "recipients"), "notify")
336
339
  channels = notify.get("channels", DEFAULT_NOTIFY["channels"])
337
340
  if not isinstance(channels, list) or not channels:
338
341
  raise _invalid(f"notify.channels must be a non-empty list of {list(NOTIFY_CHANNELS)}", "notify.channels")
@@ -342,7 +345,13 @@ def validate_notify(value: Any) -> Dict[str, Any]:
342
345
  raise _invalid(f"notify.channels[{i}] must be one of {list(NOTIFY_CHANNELS)}", f"notify.channels[{i}]")
343
346
  if ch not in out:
344
347
  out.append(ch)
345
- return {"channels": [c for c in NOTIFY_CHANNELS if c in out]}
348
+ result = {"channels": [c for c in NOTIFY_CHANNELS if c in out]}
349
+ if "recipients" in notify:
350
+ recipients = validate_email_allowed_recipients(notify["recipients"], field="notify.recipients")
351
+ if not recipients:
352
+ raise _invalid("Choose at least one result recipient", "notify.recipients")
353
+ result["recipients"] = recipients
354
+ return result
346
355
 
347
356
 
348
357
  def validate_policy(value: Any) -> Dict[str, Any]:
@@ -0,0 +1,120 @@
1
+ """AbstractCore's MCP clients, reached through AbstractRuntime (the gateway's import boundary).
2
+
3
+ The gateway may not import `abstractcore` directly (tests/test_gateway_import_boundary.py). Everything
4
+ it needs to test a registered MCP server and to call that server's tools from a run lives here:
5
+
6
+ - `open_mcp_client`: a connected-on-demand client for one server (stdio or Streamable HTTP). A stdio
7
+ server starts with exactly the environment given (`inherit_env=False`), so no gateway secret leaks
8
+ into a third-party process.
9
+ - `mcp_tool_spec`: one server tool as the spec agents see, named `mcp::<server>::<tool>`.
10
+ - `call_mcp_tool`: one `tools/call`, mapped to the runtime's tool result convention
11
+ `(success, output, error)` (the same mapping `McpToolExecutor` uses).
12
+ - the client error classes, for callers that turn failures into sentences.
13
+
14
+ Requires the AbstractCore MCP clients with `initialize()` and `inherit_env` (abstractcore round 3).
15
+ """
16
+ from __future__ import annotations
17
+
18
+ from typing import Any, Dict, Mapping, Optional, Sequence, Tuple
19
+
20
+ from abstractcore.mcp import ( # noqa: F401 - re-exported names
21
+ MCP_TOOL_PREFIX,
22
+ McpClient,
23
+ McpServerInfo,
24
+ McpStdioClient,
25
+ mcp_tool_to_abstractcore_tool_spec,
26
+ namespaced_tool_name,
27
+ parse_namespaced_tool_name,
28
+ )
29
+ from abstractcore.mcp.client import McpError, McpHttpError, McpProtocolError, McpRpcError # noqa: F401
30
+
31
+
32
+ def is_mcp_tool_name(name: Any) -> bool:
33
+ """True for a namespaced MCP tool name (`mcp::<server>::<tool>`)."""
34
+ return parse_namespaced_tool_name(str(name or "")) is not None
35
+
36
+
37
+ def open_mcp_client(
38
+ *,
39
+ transport: str,
40
+ command: str = "",
41
+ args: Sequence[str] = (),
42
+ cwd: Optional[str] = None,
43
+ env: Optional[Mapping[str, str]] = None,
44
+ url: str = "",
45
+ headers: Optional[Mapping[str, str]] = None,
46
+ timeout_s: Optional[float] = 30.0,
47
+ client_name: str = "abstractgateway",
48
+ ) -> Any:
49
+ """A client for one MCP server. stdio starts the process now (raises FileNotFoundError and
50
+ friends when it cannot start); http connects on the first request. Call `initialize()` first."""
51
+ if transport == "stdio":
52
+ if not str(command or "").strip():
53
+ raise ValueError("a stdio MCP server needs a command")
54
+ return McpStdioClient(
55
+ command=[str(command)] + [str(a) for a in args],
56
+ cwd=cwd or None,
57
+ env=dict(env or {}),
58
+ inherit_env=False,
59
+ timeout_s=timeout_s,
60
+ client_name=client_name,
61
+ )
62
+ if transport == "http":
63
+ if not str(url or "").strip():
64
+ raise ValueError("an http MCP server needs a URL")
65
+ return McpClient(url=str(url), headers=dict(headers or {}), timeout_s=timeout_s, client_name=client_name)
66
+ raise ValueError(f"unknown MCP transport {transport!r} (stdio or http)")
67
+
68
+
69
+ def close_mcp_client(client: Any) -> None:
70
+ """Close the client; a stdio server still running afterwards is killed."""
71
+ try:
72
+ client.close()
73
+ except Exception: # noqa: BLE001
74
+ pass
75
+ proc = getattr(client, "_proc", None)
76
+ if proc is not None and proc.poll() is None:
77
+ try:
78
+ proc.kill()
79
+ proc.wait(timeout=2)
80
+ except Exception: # noqa: BLE001
81
+ pass
82
+
83
+
84
+ def mcp_tool_spec(*, server_id: str, tool: Dict[str, Any], transport: str) -> Dict[str, Any]:
85
+ """The agent-facing spec of one MCP tool ({name: mcp::<server>::<tool>, description, parameters,
86
+ tags, origin}). `tool` is a tools/list entry ({name, description, inputSchema}). The origin carries
87
+ the server id and transport only — never a URL, header or command."""
88
+ server = McpServerInfo(server_id=server_id, url=f"{transport}://{server_id}", transport=transport)
89
+ spec = mcp_tool_to_abstractcore_tool_spec(tool, server=server)
90
+ origin = dict(spec.get("origin") or {})
91
+ origin.pop("url", None)
92
+ spec["origin"] = origin
93
+ return spec
94
+
95
+
96
+ def call_mcp_tool(client: Any, *, tool_name: str, arguments: Optional[Dict[str, Any]] = None) -> Tuple[bool, Any, Optional[str]]:
97
+ """One tools/call → (success, output, error). Raises the client's errors (the caller words them)."""
98
+ from .tool_executor import _mcp_result_to_error, _mcp_result_to_output
99
+
100
+ result = client.call_tool(name=tool_name, arguments=dict(arguments or {}))
101
+ err = _mcp_result_to_error(result)
102
+ if err is not None:
103
+ return False, None, err
104
+ return True, _mcp_result_to_output(result), None
105
+
106
+
107
+ __all__ = [
108
+ "MCP_TOOL_PREFIX",
109
+ "McpError",
110
+ "McpHttpError",
111
+ "McpProtocolError",
112
+ "McpRpcError",
113
+ "call_mcp_tool",
114
+ "close_mcp_client",
115
+ "is_mcp_tool_name",
116
+ "mcp_tool_spec",
117
+ "namespaced_tool_name",
118
+ "open_mcp_client",
119
+ "parse_namespaced_tool_name",
120
+ ]
@@ -166,3 +166,16 @@ def test_the_longest_accepted_interval_runs():
166
166
  binding = {"binding_id": "b", "source_id": "schedule", "source_version": 1, "config": cfg}
167
167
  state = a.admit(binding, state=a.initial_state(cfg), now=NOW)["state"]
168
168
  assert a.prepare(binding, state=state, now=NOW)["until"] == "2027-01-02T00:00:00+00:00"
169
+
170
+
171
+ @pytest.mark.parametrize("limit", [0, -1, True, False, 1.5, "30000", None])
172
+ def test_growing_context_rejects_invalid_token_limit(limit):
173
+ with pytest.raises(AutomationError) as exc:
174
+ _build(context={"mode": "growing", "growing": {"max_tokens": limit}})
175
+ assert exc.value.field == "context.growing.max_tokens"
176
+
177
+
178
+ def test_growing_context_keeps_custom_token_limit():
179
+ assert _build(context={"mode": "growing", "growing": {"max_tokens": 30_000}})["context"] == {
180
+ "mode": "growing", "growing": {"max_tokens": 30_000},
181
+ }
@@ -0,0 +1,59 @@
1
+ """Email result is a user delivery choice, independent of model notifications."""
2
+
3
+ import pytest
4
+
5
+ from automation_harness import Clock, at, children, drive, make_runtime, make_stores, request
6
+ from abstractruntime.automations import apply_automation_command, create_automation, get_automation
7
+ from abstractruntime.automations.attention import list_attention
8
+ from abstractruntime.automations.models import AutomationError, validate_notify
9
+
10
+
11
+ @pytest.mark.parametrize("store", ["json", "sqlite"])
12
+ @pytest.mark.parametrize("model_notify", [None, False, {"title": "Short notice", "body": "Only a summary"}])
13
+ def test_email_result_delivers_full_answer_and_revised_recipients(tmp_path, monkeypatch, store, model_notify):
14
+ runtime = make_runtime(*make_stores(store, tmp_path))
15
+ clock = Clock(monkeypatch)
16
+ req = request(input_data={"prompt": "Full result " * 1000, "notify": model_notify})
17
+ req["notify"] = {"channels": ["console", "email"], "recipients": ["self", "FIRST@example.test"]}
18
+ aid, _ = create_automation(runtime, req, now=clock.now)
19
+ drive(runtime, aid)
20
+ first = children(runtime, aid)[0]
21
+ [item] = list_attention(runtime.ledger_store, aid)["items"]
22
+ assert item["email_result"] == first.output["response"]
23
+ assert len(item["email_result"]) > 2000
24
+ assert item["recipients"] == ["self", "first@example.test"]
25
+ # Choosing result recipients never grants model tools permission to email them.
26
+ assert first.vars["_runtime"]["email_allowed_recipients"] == ["self"]
27
+ revised = apply_automation_command(runtime, automation_id=aid, command_id="change-recipient",
28
+ type="automation.revise", now=clock.now,
29
+ payload={"changes": {"notify": {"channels": ["console", "email"], "recipients": ["second@example.test"]}}})
30
+ assert revised["status"] == "applied"
31
+ at(runtime, clock, aid, "2026-01-01T00:02:00+00:00")
32
+ items = list_attention(runtime.ledger_store, aid)["items"]
33
+ assert [i["recipients"] for i in items] == [["self", "first@example.test"], ["second@example.test"]]
34
+ assert get_automation(runtime.run_store, aid)["definition"]["policy"]["email_allowed_recipients"] == ["self"]
35
+ disabled = apply_automation_command(runtime, automation_id=aid, command_id="disable-email-result",
36
+ type="automation.revise", now=clock.now,
37
+ payload={"changes": {"notify": {"channels": ["console"]}}})
38
+ assert disabled["status"] == "applied"
39
+ at(runtime, clock, aid, "2026-01-01T00:04:00+00:00")
40
+ assert len(children(runtime, aid)) == 3
41
+ final_items = list_attention(runtime.ledger_store, aid)["items"]
42
+ # A model-authored notice may remain, but opt-out never carries an email result.
43
+ assert [i["index"] for i in final_items if "email_result" in i] == [1, 2]
44
+
45
+
46
+ @pytest.mark.parametrize("store", ["json", "sqlite"])
47
+ def test_console_only_quiet_run_stays_quiet(tmp_path, monkeypatch, store):
48
+ runtime = make_runtime(*make_stores(store, tmp_path))
49
+ clock = Clock(monkeypatch)
50
+ aid, _ = create_automation(runtime, request(input_data={"prompt": "Quiet", "notify": False}), now=clock.now)
51
+ drive(runtime, aid)
52
+ assert list_attention(runtime.ledger_store, aid)["items"] == []
53
+
54
+
55
+ @pytest.mark.parametrize("recipients", [[], "self", ["bad"], ["Name <a@example.test>"], [True]])
56
+ def test_result_recipient_validation_reports_notify_field(recipients):
57
+ with pytest.raises(AutomationError) as exc:
58
+ validate_notify({"channels": ["email"], "recipients": recipients})
59
+ assert exc.value.field.startswith("notify.recipients")
@@ -159,3 +159,42 @@ def test_the_context_mode_decides_use_context_not_a_stale_target_input(env, tmp_
159
159
  fork = runtime.get_state(started["run_id"])
160
160
  assert fork.vars["use_context"] is True
161
161
  assert fork.vars["_runtime"]["automation_context"] == {"mode": "discussion", "use_context": True, "target_use_context": False}
162
+
163
+
164
+ @pytest.mark.parametrize("env", STORES, indirect=True)
165
+ def test_custom_growing_budget_is_persisted_and_revised_for_future_runs(env):
166
+ from automation_harness import request
167
+ from abstractruntime.automations import create_automation, get_automation, apply_automation_command
168
+ from abstractruntime.core.models import RunState
169
+
170
+ runtime, clock = env
171
+ req = request(mode="growing")
172
+ req["context"]["growing"] = {"max_tokens": 30_000}
173
+ aid, _ = create_automation(runtime, req, now=clock.now)
174
+ # Enough complete turns to exceed both windows, without an oversized turn.
175
+ for i in range(30):
176
+ ts = f"2025-12-31T23:{i:02d}:00+00:00"
177
+ runtime.run_store.save(RunState(
178
+ run_id=f"budget-prior-{i}", workflow_id="echo", status=RunStatus.COMPLETED, current_node="done",
179
+ vars={"prompt": f"question {i}"}, output={"response": "word " * 3000},
180
+ created_at=ts, updated_at=ts, session_id=f"automation:{aid}", actor_id="t",
181
+ ))
182
+ drive(runtime, aid)
183
+ first = children(runtime, aid)[0]
184
+ receipt = first.vars["_runtime"]["session_history"]
185
+ assert receipt["max_tokens"] == 30_000
186
+ assert 0 < receipt["replayed_tokens"] <= 30_000 and receipt["dropped_messages"] > 0
187
+ result = apply_automation_command(runtime, automation_id=aid, command_id="budget-revise",
188
+ type="automation.revise", now=clock.now,
189
+ payload={"changes": {"context": {"mode": "growing", "growing": {"max_tokens": 10_000}}}})
190
+ assert result["status"] == "applied"
191
+ detail = get_automation(runtime.run_store, aid)
192
+ assert detail["definition"]["context"]["growing"]["max_tokens"] == 10_000
193
+ from abstractruntime.automation_queries import automation_summary
194
+ assert automation_summary(runtime.get_state(aid))["growing_max_tokens"] == 10_000
195
+ at(runtime, clock, aid, "2026-01-01T00:02:00+00:00")
196
+ second = children(runtime, aid)[1]
197
+ assert second.vars["_runtime"]["session_history"]["max_tokens"] == 10_000
198
+ assert second.vars["_runtime"]["session_history"]["replayed_tokens"] <= 10_000
199
+ assert len(second.vars["context"]["messages"]) < len(first.vars["context"]["messages"])
200
+ assert runtime.get_state(first.run_id).vars["_runtime"]["session_history"]["max_tokens"] == 30_000