AbstractRuntime 0.8.5__tar.gz → 0.9.1__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 (690) hide show
  1. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/.github/workflows/ci.yml +53 -0
  2. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/CHANGELOG.md +39 -2
  3. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/PKG-INFO +4 -4
  4. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/README.md +1 -1
  5. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/api.md +7 -1
  6. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/automations.md +3 -2
  7. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/faq.md +6 -4
  8. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/integrations/abstractcore.md +31 -7
  9. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/llms-full.txt +48 -15
  10. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/llms.txt +3 -3
  11. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/pyproject.toml +6 -4
  12. abstractruntime-0.9.1/release-notes.md +12 -0
  13. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/commands.py +39 -1
  14. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/controller.py +14 -0
  15. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/runtime.py +15 -0
  16. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/tools.py +28 -0
  17. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/__init__.py +18 -0
  18. abstractruntime-0.9.1/src/abstractruntime/integrations/abstractcore/command_sandbox_host.py +29 -0
  19. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +4 -0
  20. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +28 -3
  21. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/run_facade.py +117 -114
  22. abstractruntime-0.9.1/src/abstractruntime/integrations/abstractcore/structured_facade.py +51 -0
  23. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/tool_executor.py +30 -4
  24. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +168 -23
  25. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/utils/workspace_paths.py +48 -2
  26. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/compiler.py +10 -1
  27. abstractruntime-0.9.1/tests/test_abstractcore_structured_facade.py +54 -0
  28. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_commands.py +38 -0
  29. abstractruntime-0.9.1/tests/test_automation_occurrence_input_resolver.py +92 -0
  30. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_tool_approval.py +4 -1
  31. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_browser_probe_target_walling.py +15 -0
  32. abstractruntime-0.9.1/tests/test_command_sandbox_host_facade.py +27 -0
  33. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_packaging_extras.py +3 -3
  34. abstractruntime-0.9.1/tests/test_r12_workspace_sandbox.py +407 -0
  35. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_shell_tool_exposure.py +3 -1
  36. abstractruntime-0.9.1/tests/test_voice_stream_is_not_a_wait.py +256 -0
  37. abstractruntime-0.9.1/tests/test_workspace_context_allowed_workspaces.py +75 -0
  38. abstractruntime-0.9.1/tests/test_workspace_writable_paths.py +69 -0
  39. abstractruntime-0.8.5/release-notes.md +0 -1
  40. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/.github/workflows/release.yml +0 -0
  41. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/.gitignore +0 -0
  42. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/ACKNOWLEDGMENTS.md +0 -0
  43. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/CODE_OF_CONDUCT.md +0 -0
  44. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/CONTRIBUTING.md +0 -0
  45. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/LICENSE +0 -0
  46. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/README.md +0 -0
  47. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/ROADMAP.md +0 -0
  48. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/SECURITY.md +0 -0
  49. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
  50. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
  51. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
  52. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
  53. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
  54. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
  55. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
  56. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/adr/README.md +0 -0
  57. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/architecture.md +0 -0
  58. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/artifacts.md +0 -0
  59. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/README.md +0 -0
  60. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/001_runtime_kernel.md +0 -0
  61. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
  62. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
  63. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
  64. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
  65. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
  66. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
  67. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
  68. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/003_wait_primitives.md +0 -0
  69. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
  70. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
  71. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
  72. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
  73. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/004_scheduler_driver.md +0 -0
  74. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
  75. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
  76. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
  77. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/009_artifact_store.md +0 -0
  78. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/010_examples_and_composition.md +0 -0
  79. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/011_subworkflow_support.md +0 -0
  80. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
  81. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
  82. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
  83. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
  84. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
  85. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
  86. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
  87. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
  88. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
  89. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
  90. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
  91. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
  92. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
  93. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
  94. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
  95. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
  96. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
  97. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
  98. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
  99. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
  100. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
  101. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
  102. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
  103. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/004_tests.md +0 -0
  104. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/005_docs_updates.md +0 -0
  105. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
  106. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
  107. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
  108. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/README.md +0 -0
  109. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
  110. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
  111. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
  112. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
  113. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
  114. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
  115. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
  116. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
  117. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
  118. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
  119. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
  120. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
  121. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
  122. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
  123. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
  124. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_portability/README.md +0 -0
  125. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
  126. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
  127. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
  128. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
  129. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
  130. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
  131. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
  132. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
  133. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
  134. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
  135. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
  136. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
  137. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
  138. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
  139. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
  140. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
  141. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
  142. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
  143. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
  144. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
  145. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
  146. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
  147. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
  148. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
  149. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
  150. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
  151. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
  152. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
  153. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
  154. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/email.md +0 -0
  155. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/entity-runtime.md +0 -0
  156. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/evidence.md +0 -0
  157. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/getting-started.md +0 -0
  158. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/limits.md +0 -0
  159. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/manual_testing.md +0 -0
  160. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/mcp-worker.md +0 -0
  161. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/proposal.md +0 -0
  162. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/provenance.md +0 -0
  163. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/snapshots.md +0 -0
  164. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/tool-approval.md +0 -0
  165. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/tools-comms.md +0 -0
  166. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/troubleshooting.md +0 -0
  167. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/docs/workflow-bundles.md +0 -0
  168. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/01_hello_world.py +0 -0
  169. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/02_ask_user.py +0 -0
  170. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/03_wait_until.py +0 -0
  171. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/04_multi_step.py +0 -0
  172. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/05_persistence.py +0 -0
  173. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/06_llm_integration.py +0 -0
  174. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/07_react_agent.py +0 -0
  175. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/examples/README.md +0 -0
  176. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/mkdocs.yml +0 -0
  177. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/pytest.ini +0 -0
  178. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/scripts/backfill_diary_edges.py +0 -0
  179. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/scripts/generate_llms_full.py +0 -0
  180. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/__init__.py +0 -0
  181. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automation_queries.py +0 -0
  182. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/__init__.py +0 -0
  183. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/adapters.py +0 -0
  184. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/attention.py +0 -0
  185. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/bundle.py +0 -0
  186. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
  187. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
  188. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/ledger.py +0 -0
  189. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/models.py +0 -0
  190. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/automations/service.py +0 -0
  191. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/__init__.py +0 -0
  192. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/config.py +0 -0
  193. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/effect_cancellation.py +0 -0
  194. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/event_keys.py +0 -0
  195. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/health.py +0 -0
  196. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/live_deltas.py +0 -0
  197. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/models.py +0 -0
  198. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/policy.py +0 -0
  199. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/progress_channel.py +0 -0
  200. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/run_attribution.py +0 -0
  201. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/run_identity.py +0 -0
  202. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/run_lifecycle.py +0 -0
  203. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/spec.py +0 -0
  204. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/tool_scope.py +0 -0
  205. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/core/vars.py +0 -0
  206. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/documents/__init__.py +0 -0
  207. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/documents/charts.py +0 -0
  208. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/documents/docx.py +0 -0
  209. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/documents/pdf.py +0 -0
  210. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/__init__.py +0 -0
  211. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/actions.py +0 -0
  212. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/automations.py +0 -0
  213. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/binding.py +0 -0
  214. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/feeder.py +0 -0
  215. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/frame.py +0 -0
  216. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/email/inbox.py +0 -0
  217. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/evidence/__init__.py +0 -0
  218. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/evidence/recorder.py +0 -0
  219. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/history_bundle.py +0 -0
  220. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/__init__.py +0 -0
  221. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/act_only.py +0 -0
  222. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/chat.py +0 -0
  223. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/communities.py +0 -0
  224. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/diary.py +0 -0
  225. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/digest.py +0 -0
  226. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/entity_runtime.py +0 -0
  227. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/fingerprint.py +0 -0
  228. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/lease.py +0 -0
  229. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/life.py +0 -0
  230. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/memory_reader.py +0 -0
  231. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/night_voice.py +0 -0
  232. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/phase_graph.py +0 -0
  233. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/phase_spec.py +0 -0
  234. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/prelude.py +0 -0
  235. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/prompt_overlay.py +0 -0
  236. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/reflection.py +0 -0
  237. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
  238. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/substrate.py +0 -0
  239. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/tool_effects.py +0 -0
  240. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/tool_policy.py +0 -0
  241. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/identity/visit_workflow.py +0 -0
  242. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/__init__.py +0 -0
  243. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
  244. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
  245. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
  246. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
  247. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
  248. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
  249. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
  250. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
  251. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
  252. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
  253. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
  254. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
  255. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
  256. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
  257. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/mcp_facade.py +0 -0
  258. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
  259. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
  260. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
  261. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
  262. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/server_facade.py +0 -0
  263. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
  264. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
  265. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
  266. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
  267. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
  268. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
  269. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
  270. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
  271. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
  272. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
  273. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/__init__.py +0 -0
  274. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/active_context.py +0 -0
  275. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/active_memory.py +0 -0
  276. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/compaction.py +0 -0
  277. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/kg_packets.py +0 -0
  278. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/memact_composer.py +0 -0
  279. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/recall_levels.py +0 -0
  280. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/memory/token_budget.py +0 -0
  281. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/rendering/__init__.py +0 -0
  282. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
  283. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/rendering/json_stringify.py +0 -0
  284. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/scheduler/__init__.py +0 -0
  285. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/scheduler/convenience.py +0 -0
  286. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/scheduler/multi_store.py +0 -0
  287. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/scheduler/registry.py +0 -0
  288. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/scheduler/scheduler.py +0 -0
  289. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/session_history.py +0 -0
  290. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/session_turns.py +0 -0
  291. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/__init__.py +0 -0
  292. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/artifacts.py +0 -0
  293. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/base.py +0 -0
  294. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/commands.py +0 -0
  295. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/in_memory.py +0 -0
  296. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/json_files.py +0 -0
  297. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/lease.py +0 -0
  298. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/ledger_chain.py +0 -0
  299. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/ledger_slim.py +0 -0
  300. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/observable.py +0 -0
  301. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/offloading.py +0 -0
  302. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/serialize.py +0 -0
  303. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/snapshots.py +0 -0
  304. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/sqlite.py +0 -0
  305. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/storage/steer_sidecar.py +0 -0
  306. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/__init__.py +0 -0
  307. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/email_received.py +0 -0
  308. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/manual.py +0 -0
  309. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/protocol.py +0 -0
  310. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/registry.py +0 -0
  311. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/triggers/schedule.py +0 -0
  312. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/turn_grounding.py +0 -0
  313. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/utils/__init__.py +0 -0
  314. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/utils/atomic_files.py +0 -0
  315. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/utils/file_filters.py +0 -0
  316. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
  317. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
  318. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
  319. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
  320. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
  321. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
  322. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
  323. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
  324. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
  325. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
  326. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
  327. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
  328. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
  329. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
  330. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
  331. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
  332. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
  333. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/executor.py +0 -0
  334. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
  335. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
  336. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
  337. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
  338. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
  339. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/workflow_bundle/models.py +0 -0
  340. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/workflow_bundle/packer.py +0 -0
  341. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/workflow_bundle/reader.py +0 -0
  342. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/src/abstractruntime/workflow_bundle/registry.py +0 -0
  343. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/README.md +0 -0
  344. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/automation_harness.py +0 -0
  345. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/conftest.py +0 -0
  346. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/email_wp2_support.py +0 -0
  347. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/live_email/conftest.py +0 -0
  348. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/live_email/live_email_support.py +0 -0
  349. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/live_email/test_email_live_runtime.py +0 -0
  350. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_comms_facade.py +0 -0
  351. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_discovery_facade.py +0 -0
  352. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_host_facade.py +0 -0
  353. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_run_facade.py +0 -0
  354. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_server_facade.py +0 -0
  355. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_abstractcore_telegram_facade.py +0 -0
  356. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_active_context_policy.py +0 -0
  357. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_active_memory.py +0 -0
  358. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_agora_agent_alias_identity.py +0 -0
  359. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_agora_tools_http.py +0 -0
  360. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_analyze_media_addressing_and_walling.py +0 -0
  361. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_answer_user_effect.py +0 -0
  362. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_artifacts.py +0 -0
  363. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_controller.py +0 -0
  364. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_controller_recovery.py +0 -0
  365. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_definition.py +0 -0
  366. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_discussion_isolation.py +0 -0
  367. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_email_results.py +0 -0
  368. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_growing_context.py +0 -0
  369. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_index.py +0 -0
  370. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_next_fire.py +0 -0
  371. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_occurrence_recovery.py +0 -0
  372. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_replay_read_only.py +0 -0
  373. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_retry.py +0 -0
  374. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_session_turns.py +0 -0
  375. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_automation_status.py +0 -0
  376. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_budget_law_no_unrequested_caps.py +0 -0
  377. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_capability_default_reasoning.py +0 -0
  378. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_chat_summarizer_integration.py +0 -0
  379. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_code_node_restricted_python.py +0 -0
  380. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_command_store.py +0 -0
  381. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_compaction_helpers.py +0 -0
  382. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_compaction_summarizer_route.py +0 -0
  383. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_config_facade_models_engines.py +0 -0
  384. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_control_adapter_while.py +0 -0
  385. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_controller_bundle_packaged.py +0 -0
  386. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_crash_ordering_inversions.py +0 -0
  387. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_create_if_absent.py +0 -0
  388. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_data_registry_facade.py +0 -0
  389. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_camera_gating.py +0 -0
  390. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_comms_gating.py +0 -0
  391. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_include_skim_files.py +0 -0
  392. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_include_skim_folders.py +0 -0
  393. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_include_skim_web.py +0 -0
  394. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_default_tools_search_files_executor.py +0 -0
  395. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_diary_capture.py +0 -0
  396. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_diary_write_rescue.py +0 -0
  397. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_directory_lease.py +0 -0
  398. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_disabled_toolsets_seam.py +0 -0
  399. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_discovery_survives_unbuildable_default.py +0 -0
  400. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_discovery_tts_unavailable_reason.py +0 -0
  401. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_discovery_voice_openai_api_key.py +0 -0
  402. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_discussion_session_anchor.py +0 -0
  403. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_document_markdown_tables.py +0 -0
  404. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_document_renderers_hr_quote.py +0 -0
  405. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_durable_toolsets.py +0 -0
  406. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_durable_write_discipline.py +0 -0
  407. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
  408. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_effect_cancellation.py +0 -0
  409. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_effect_issuance_idempotency.py +0 -0
  410. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_effect_payload_stays_json_serializable.py +0 -0
  411. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_election_consequence_teaching.py +0 -0
  412. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_binding_and_refiner.py +0 -0
  413. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_gate_fixes.py +0 -0
  414. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_inbox_and_trigger.py +0 -0
  415. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_regate_fixes.py +0 -0
  416. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_review_fixes.py +0 -0
  417. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_self_trigger_loop.py +0 -0
  418. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_email_toolset_and_walls.py +0 -0
  419. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_emergence_experiment.py +0 -0
  420. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_emit_event_uses_wait_index.py +0 -0
  421. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_emit_event_without_workflow_registry.py +0 -0
  422. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_endpoint_profile_route_context.py +0 -0
  423. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_awake_memory_fixes.py +0 -0
  424. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_brain_effects.py +0 -0
  425. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_chat_driver.py +0 -0
  426. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_chat_tools_reflection.py +0 -0
  427. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_diary.py +0 -0
  428. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_execute_tool.py +0 -0
  429. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_fetch_url_tool.py +0 -0
  430. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_history_window.py +0 -0
  431. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_life_loop.py +0 -0
  432. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_memory_richness.py +0 -0
  433. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_phase_graph_conformance.py +0 -0
  434. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_react_visit_window.py +0 -0
  435. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_recent_memories.py +0 -0
  436. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_runtime.py +0 -0
  437. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_search_memory.py +0 -0
  438. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
  439. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_substrate_resolution.py +0 -0
  440. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_visit_honesty.py +0 -0
  441. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_workspace_cap.py +0 -0
  442. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_entity_workspace_tools.py +0 -0
  443. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_event_wait_index.py +0 -0
  444. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
  445. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_evidence_recorder.py +0 -0
  446. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
  447. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_execute_command_output_offload.py +0 -0
  448. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_execution_capability_discovery.py +0 -0
  449. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_explicit_eject_other_clients.py +0 -0
  450. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_factory_default_retry_policy.py +0 -0
  451. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
  452. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_format_repair_nudge.py +0 -0
  453. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_fresh_install_no_provider.py +0 -0
  454. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_gateway_facades_c4899.py +0 -0
  455. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_git_read_only_refiner.py +0 -0
  456. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_hf_process_residency_merge.py +0 -0
  457. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_history_window_multimodal.py +0 -0
  458. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_hot_path_store_reads.py +0 -0
  459. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_indexed_idempotency_lookup.py +0 -0
  460. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_integration_abstractcore.py +0 -0
  461. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_integrations_abstractcore.py +0 -0
  462. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_json_file_run_store_children_index.py +0 -0
  463. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_json_run_cache_bound.py +0 -0
  464. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_json_store_scan_memo.py +0 -0
  465. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_jsonl_ledger_recovery.py +0 -0
  466. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_kg_learn_and_recall_contract.py +0 -0
  467. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_ledger_chain.py +0 -0
  468. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_ledger_record_slimming.py +0 -0
  469. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_ledger_subscription.py +0 -0
  470. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_live_token_deltas.py +0 -0
  471. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_media_artifact_refs.py +0 -0
  472. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
  473. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
  474. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_payload_shape_refusal.py +0 -0
  475. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_requires_prompt.py +0 -0
  476. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_response_schema_normalization.py +0 -0
  477. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_structured_output_fallback.py +0 -0
  478. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_text_phase_progress.py +0 -0
  479. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_truncation_retry_contract.py +0 -0
  480. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_use_context_appends_turn.py +0 -0
  481. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
  482. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_client_grounding_tail.py +0 -0
  483. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_client_media_artifacts.py +0 -0
  484. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_client_system_context.py +0 -0
  485. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_client_tool_call_parsing.py +0 -0
  486. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_retry_classification.py +0 -0
  487. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_llm_streaming_on_token.py +0 -0
  488. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_local_helper_tool_exposure.py +0 -0
  489. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_local_residency_host_sweep.py +0 -0
  490. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
  491. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_max_iterations_ceiling.py +0 -0
  492. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mcp_remote_tool_executor.py +0 -0
  493. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mcp_runs_untrusted_and_facade.py +0 -0
  494. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mcp_worker_logging.py +0 -0
  495. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mcp_worker_security.py +0 -0
  496. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mcp_worker_stdio.py +0 -0
  497. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_media_artifact_resolution.py +0 -0
  498. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_media_capability_default_routing.py +0 -0
  499. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_media_only_requests_skip_text_client.py +0 -0
  500. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_media_subprocess.py +0 -0
  501. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memact_composer_from_kg_result.py +0 -0
  502. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_appraise_handler.py +0 -0
  503. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_communities.py +0 -0
  504. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
  505. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_packets.py +0 -0
  506. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_predicate_aliasing.py +0 -0
  507. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_query_packetization_restart.py +0 -0
  508. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
  509. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
  510. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_note_effect.py +0 -0
  511. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_query_effect.py +0 -0
  512. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_query_rich_filters.py +0 -0
  513. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
  514. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_seam_handlers.py +0 -0
  515. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_seam_sqlite_durability.py +0 -0
  516. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_memory_tag_effect.py +0 -0
  517. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mlx_generation_serialization.py +0 -0
  518. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_mlx_process_residency_merge.py +0 -0
  519. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_model_eject_cancel.py +0 -0
  520. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_model_residency_clean_switch.py +0 -0
  521. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_model_residency_control_plane.py +0 -0
  522. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
  523. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_multi_store_scheduler.py +0 -0
  524. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_multimodal_abstractcore_integration.py +0 -0
  525. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_native_mlx_application_wiring.py +0 -0
  526. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_native_mlx_execution_controls_live.py +0 -0
  527. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_native_tool_channel.py +0 -0
  528. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_night_voice.py +0 -0
  529. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_no_default_provider_refusal_ux.py +0 -0
  530. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_offload_answer_chain_c4978.py +0 -0
  531. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
  532. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_offloading.py +0 -0
  533. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_parallel_readonly_tool_execution.py +0 -0
  534. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_pause_resume.py +0 -0
  535. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_pdf_unicode_rendering.py +0 -0
  536. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_personal_cycle.py +0 -0
  537. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_phantom_attachment_index.py +0 -0
  538. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_phase_graph_artifact_control.py +0 -0
  539. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_phase_graph_obedience.py +0 -0
  540. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_phase_vocabulary_migration.py +0 -0
  541. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
  542. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_cache_export_import.py +0 -0
  543. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
  544. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_cache_modules.py +0 -0
  545. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_cache_posture_inheritance.py +0 -0
  546. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
  547. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_prompt_overlay.py +0 -0
  548. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_provider_endpoint_profile_resolution.py +0 -0
  549. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_provider_pin_routing_isolation.py +0 -0
  550. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_queryable_run_store.py +0 -0
  551. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
  552. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_read_idle_threading.py +0 -0
  553. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_readoption_experiment.py +0 -0
  554. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_real_integration.py +0 -0
  555. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_realize_election.py +0 -0
  556. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_recall_levels_policy.py +0 -0
  557. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_remote_client_cancel.py +0 -0
  558. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_remote_llm_client.py +0 -0
  559. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_remote_speculation_defaults.py +0 -0
  560. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_rendering_agent_trace_report.py +0 -0
  561. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_rendering_json_stringify.py +0 -0
  562. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_report_branding.py +0 -0
  563. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_resident_media_generation.py +0 -0
  564. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_resume_concurrent_same_wait.py +0 -0
  565. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_retry_idempotency.py +0 -0
  566. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_run_history_bundle.py +0 -0
  567. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_run_index_workspace_root.py +0 -0
  568. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_run_mutation_lock.py +0 -0
  569. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_run_scoped_tool_policy.py +0 -0
  570. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_run_tool_scope_ceiling.py +0 -0
  571. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_browser_session_boundary.py +0 -0
  572. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
  573. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_default_provider_model_refresh.py +0 -0
  574. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_effect_invocation_trace.py +0 -0
  575. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_health_and_bounded_vars.py +0 -0
  576. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_install_boundary.py +0 -0
  577. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
  578. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_node_traces.py +0 -0
  579. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_start_seeds_tool_support.py +0 -0
  580. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_runtime_tick_step_gate.py +0 -0
  581. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_scheduler.py +0 -0
  582. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_send_email_refiner.py +0 -0
  583. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_send_email_self_default_policy.py +0 -0
  584. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
  585. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_history.py +0 -0
  586. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_prompt_cache_attribution.py +0 -0
  587. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_prompt_cache_visibility.py +0 -0
  588. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_route_stamp.py +0 -0
  589. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_session_start_cost.py +0 -0
  590. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_snapshots.py +0 -0
  591. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_speculation_inheritance.py +0 -0
  592. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_speculation_reaches_provider_construction.py +0 -0
  593. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_sqlite_ledger_store.py +0 -0
  594. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_start_subworkflow_async_wait.py +0 -0
  595. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
  596. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
  597. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_steer_sidecar.py +0 -0
  598. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_storage_deletion.py +0 -0
  599. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_structured_output_schema_enum.py +0 -0
  600. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_subworkflow.py +0 -0
  601. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_terminal_effect_completion.py +0 -0
  602. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
  603. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_thinking_inheritance.py +0 -0
  604. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
  605. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_approval_executor.py +0 -0
  606. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_approval_resume_executes.py +0 -0
  607. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_approval_wait_key_identity.py +0 -0
  608. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_calls_idempotency_keys.py +0 -0
  609. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_catalog.py +0 -0
  610. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_descriptor_registry.py +0 -0
  611. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_argument_sanitization.py +0 -0
  612. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_error_output_detection.py +0 -0
  613. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_filename_alias.py +0 -0
  614. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
  615. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_read_file_aliases.py +0 -0
  616. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_executor_timeout.py +0 -0
  617. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_inventory_facade.py +0 -0
  618. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_invoke_effect.py +0 -0
  619. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_policy_and_mounts.py +0 -0
  620. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_tool_wait_allowlist_safety.py +0 -0
  621. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_topic_election_world_model.py +0 -0
  622. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_trace_context_propagation.py +0 -0
  623. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_trigger_registry.py +0 -0
  624. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_trigger_schedule_math.py +0 -0
  625. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_turn_grounding_byte_stability.py +0 -0
  626. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_turn_grounding_carriers_a3.py +0 -0
  627. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_vars_query_effect.py +0 -0
  628. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visit_ab_fixture.py +0 -0
  629. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visit_midturn_elections.py +0 -0
  630. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visit_midturn_resume.py +0 -0
  631. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visit_workflow.py +0 -0
  632. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
  633. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
  634. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
  635. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
  636. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
  637. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
  638. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_entity_memory_nodes.py +0 -0
  639. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
  640. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_llm_call_partial_override.py +0 -0
  641. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
  642. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_memact_compose_node.py +0 -0
  643. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
  644. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
  645. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
  646. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_unknown_node_type_refuses.py +0 -0
  647. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
  648. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_add_message_builtin.py +0 -0
  649. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
  650. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_agora_react_agent.py +0 -0
  651. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_call_tool_node.py +0 -0
  652. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
  653. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_compiler_basic.py +0 -0
  654. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
  655. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_continue_on_error.py +0 -0
  656. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_edit_json_schema_node.py +0 -0
  657. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
  658. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_file_nodes_workspace.py +0 -0
  659. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_function_library.py +0 -0
  660. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_get_element_node.py +0 -0
  661. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_get_random_element_node.py +0 -0
  662. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_get_var_node.py +0 -0
  663. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_has_tools_builtin.py +0 -0
  664. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
  665. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
  666. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_make_object_node.py +0 -0
  667. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_media_nodes.py +0 -0
  668. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_memory_effect_nodes.py +0 -0
  669. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_memory_source_pins.py +0 -0
  670. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_pin_expressions.py +0 -0
  671. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_prompt_only.py +0 -0
  672. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_random_nodes.py +0 -0
  673. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_schema_enum_switch.py +0 -0
  674. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_string_contains_replace.py +0 -0
  675. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_visualflow_tool_parameters_node.py +0 -0
  676. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_voice_openai_api_key_path.py +0 -0
  677. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_w4_feelings_lens.py +0 -0
  678. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_wait_event_deadline.py +0 -0
  679. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_wait_event_prompt_metadata.py +0 -0
  680. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_wait_until_streak.py +0 -0
  681. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_wait_until_utc_normalization.py +0 -0
  682. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workflow_bundle_registry.py +0 -0
  683. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_builtin_deny.py +0 -0
  684. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
  685. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_policy_allowlist_mode.py +0 -0
  686. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
  687. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
  688. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_prompt_context.py +0 -0
  689. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_workspace_read_only.py +0 -0
  690. {abstractruntime-0.8.5 → abstractruntime-0.9.1}/tests/test_write_chart.py +0 -0
@@ -69,6 +69,59 @@ jobs:
69
69
  tests/test_trigger_registry.py \
70
70
  tests/test_workspace_read_only.py
71
71
 
72
+ # The command sandbox end to end on Linux: run vars -> TOOL_CALLS handler ->
73
+ # `_sandbox` stamp -> AbstractCore's spawning tools inside bubblewrap. The
74
+ # end-to-end tests in tests/test_r12_workspace_sandbox.py skip with their
75
+ # reason on a host without an OS sandbox, so the job above proves nothing
76
+ # about Linux. This job installs bubblewrap, lets it create user namespaces
77
+ # (Ubuntu 24.04 restricts them through AppArmor by default), and FAILS unless
78
+ # every sandbox test ran and passed: a skip here is a red job, never a green one.
79
+ linux-sandbox:
80
+ name: Linux command sandbox (bubblewrap)
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ - uses: actions/setup-python@v5
85
+ with:
86
+ python-version: "3.12"
87
+ cache: pip
88
+ - name: Install bubblewrap
89
+ run: |
90
+ sudo apt-get update
91
+ sudo apt-get install -y bubblewrap
92
+ # bwrap is not setuid on Ubuntu: it needs unprivileged user namespaces.
93
+ sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
94
+ bwrap --version
95
+ bwrap --ro-bind / / --dev /dev --proc /proc -- /bin/true
96
+ uname -r
97
+ - name: Install
98
+ run: |
99
+ python -m pip install -U pip
100
+ python -m pip install -e ".[test]"
101
+ - name: Pytest (sandbox tests must run, not skip)
102
+ run: |
103
+ python -m pytest -rs -p no:cacheprovider \
104
+ tests/test_r12_workspace_sandbox.py tests/test_command_sandbox_host_facade.py \
105
+ --junitxml=sandbox-junit.xml
106
+ - name: Assert the sandbox tests ran
107
+ run: |
108
+ python - <<'PY'
109
+ import sys
110
+ import xml.etree.ElementTree as ET
111
+
112
+ cases = list(ET.parse("sandbox-junit.xml").getroot().iter("testcase"))
113
+ skipped = [c for c in cases if c.find("skipped") is not None]
114
+ failed = [c for c in cases if c.find("failure") is not None or c.find("error") is not None]
115
+ e2e = [c for c in cases if (c.get("name") or "").startswith("test_e2e_")]
116
+ e2e_passed = [c for c in e2e if c not in skipped and c not in failed]
117
+ passed = len(cases) - len(skipped) - len(failed)
118
+ print(f"sandbox tests: {len(cases)} collected, {passed} passed, {len(skipped)} skipped, {len(failed)} failed; end-to-end passed {len(e2e_passed)}/{len(e2e)}")
119
+ for c in skipped:
120
+ print("SKIPPED:", c.get("name"), "-", (c.find("skipped").get("message") or ""))
121
+ if len(e2e) < 7 or len(e2e_passed) != len(e2e) or skipped or failed:
122
+ sys.exit("The sandbox tests did not all run and pass inside bubblewrap on this Linux host.")
123
+ PY
124
+
72
125
  build:
73
126
  name: Build distributions
74
127
  runs-on: ubuntu-latest
@@ -5,9 +5,46 @@ All notable changes to AbstractRuntime will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.9.1] - 2026-10-08
9
9
 
10
- Nothing yet.
10
+ ### Security
11
+
12
+ - `browser_probe`: a local target (path or `file://` URL) now carries the run's `_sandbox` stamp, the same scope the commands get. AbstractCore 2.25.1 serves the page from a loopback origin limited to that scope instead of `file://`, so a page cannot load refused files as subresources. Needs AbstractCore 2.25.1 (an older `browser_probe` refuses the unknown argument and runs nothing). Test: `tests/test_browser_probe_target_walling.py`.
13
+
14
+ ### Fixed
15
+
16
+ - `stream_voice(...)` is never a wait. It used to start the child run parked on `WAIT_EVENT abstractcore.voice.tts.stream:<uuid>` for the whole stream: hosts folded that waiting record into the CALLER'S run (a Read aloud during a live turn read as "Waiting for an event"), and a host that died mid-stream left the child waiting forever. Now nothing durable exists while audio streams; when the stream ends (done, error, cancel or the consumer closing it) the child run is created already COMPLETED with the outcome. Its id is allocated up front: `runtime_start` carries it as `child_run_id` (schema `abstractruntime.tts_stream.start.v2`, no `wait_key`), as does the trace metadata. A stream cut by a crash leaves no run.
17
+ - `AbstractCoreRunFacade.close_interrupted_voice_stream(child_run_id, *, reason)` finishes a legacy streamed-speech wait left by an older process (completed, `errors[0] = {"code": "interrupted", "message": reason}`); `is_interrupted_voice_stream_wait(waiting)` and `LEGACY_VOICE_STREAM_WAIT_KEY_PREFIX` recognise one (exported from `integrations.abstractcore`). AbstractGateway calls it at startup.
18
+
19
+ ### Changed
20
+
21
+ - Requires AbstractCore 2.25.1 or newer (`abstractcore>=2.25.1` in the base install and the `[apple]`/`[gpu]` extras): the Linux command sandbox reaches an allowed folder inside a refused one, and `browser_probe` accepts the run's `_sandbox` stamp.
22
+
23
+ ## [0.9.0] - 2026-10-05
24
+
25
+ ### Added
26
+
27
+ - `Runtime.set_occurrence_input_resolver(fn)`: a host hook called at each automation occurrence's admission, as `fn(definition, input_data) -> input_data`. Its answer is frozen into the occurrence's prepared inputs, so replays stay byte-identical; a non-dict answer fails the admission; with no resolver set nothing changes. AbstractGateway uses it to resolve the workspaces of an automation that follows its owner's default at each run, instead of a snapshot taken at save time. Test: `tests/test_automation_occurrence_input_resolver.py`.
28
+
29
+ - Command sandbox: `execute_command`, `shell_exec`, `local_helper_start` and AbstractAgent's `execute_python` (0.3.18 or newer; an older one fails on the unknown argument and runs nothing) receive the run's effective workspace set as the hidden `_sandbox` argument (`sandbox_stamp(scope)`, built on every call from the same workspace vars the file tools read; `execute_python` starts in the stamp's private workspace; a model- or payload-supplied `_sandbox` is always replaced or dropped), and run inside AbstractCore's OS sandbox (`abstractcore.tools.sandbox`: macOS `sandbox-exec`, Linux `bwrap` or Landlock). `local_helper_start` and the entity exec tool apply it themselves (the entity's workspace and whitelisted mounts). With no sandbox on the host, or an AbstractCore without the sandbox module, the call is refused with one sentence before anything runs and the run continues.
30
+
31
+ - `integrations.abstractcore.command_sandbox_host`: hosts configure the command sandbox through the runtime (`configure_host`, `host_policy`, `host_sandbox_kind`, `KIND_LABELS`, `KIND_NONE`, `reset_host_for_tests`; pure re-exports of `abstractcore.tools.sandbox`), so a host never imports AbstractCore directly. Used by AbstractGateway's `serve`.
32
+ - `MappingToolExecutor` never drops the `_sandbox` stamp: a tool whose signature cannot take it (an AbstractAgent older than 0.3.18) gets a failed result naming the stamp and does not run. Its argument-name normalization never maps a model key (`sandbox`, `registry_namespace`, ...) onto a hidden `_`-prefixed parameter.
33
+ - CI: a `linux-sandbox` job installs bubblewrap on Ubuntu and runs the command-sandbox tests end to end inside it (the end-to-end tests now run inside the host's OS sandbox: macOS `sandbox-exec` or Linux bubblewrap); the job fails when any of them is skipped.
34
+ - `workspace_writable_paths`: writable exceptions inside read-only roots (`workspace_read_only_paths`), the more specific rule winning. The tool scope, `path_is_read_only` and VisualFlow writers honour them; child runs and file nodes inherit the parent's exactly and never add one. Used by AbstractGateway 0.13.0 for "Allow everything, refuse listed workspaces" with a read-only default.
35
+ - `integrations.abstractcore.structured_facade` (also flat from `integrations.abstractcore`): `parse_response_format` and AbstractCore's own `ResponseFormatError`, so hosts check an OpenAI `response_format` without importing AbstractCore. Used by AbstractGateway 0.13.0's `/v1/chat/completions`.
36
+ - Workspace context of a tool-using `LLM_CALL`: after the default working directory (the run's own workspace), `Allowed workspaces:` lists each allowed workspace outside it with its mode (`(read-only)` / `(read & write)`, from `workspace_read_only_paths` and `workspace_writable_paths`), and under `all_except_ignored` `Everything else: (…)`; refused paths are never listed as allowed. Used by AbstractGateway 0.13.0 on every run start.
37
+ - `automation.unarchive`: an archived automation comes back paused with its history intact; a controller that ended because it was archived restarts and parks on its wake wait (observation `automation.unarchived`).
38
+
39
+ ### Changed
40
+
41
+ - Workspace nesting: the most specific row wins. Among `workspace_root`, `workspace_allowed_paths` and `workspace_ignored_paths`, the longest real-path prefix of a path decides (a refusal wins a tie); a refused folder no longer refuses an allowed workspace inside it, and a refused folder inside an allowed one still refuses its subtree. Built-in protection stays absolute. Same rule as AbstractGateway's validation and the sandbox profile.
42
+ - The workspace context now says "Shell commands run inside an OS sandbox limited to these workspaces." and describes refused paths as "Excluded paths (a more specific allowed workspace inside one stays reachable)".
43
+ - Requires AbstractCore 2.25.0 or newer (`abstractcore>=2.25.0` in the base install and the `[apple]`/`[gpu]` extras): the command sandbox and `structured_facade` use it.
44
+
45
+ ### Removed
46
+
47
+ - `workspace_shared_path` / `SHARED_WORKSPACE_KEY` / `shared_workspace_path` (added during 0.9.0 development, never released): AbstractGateway 0.13.0 has no shared workspace any more (round 11), so the workspace context names no "Shared workspace"; the allowed workspaces and their modes are listed as before. A stale key in a run's vars is ignored.
11
48
 
12
49
  ## [0.8.5] - 2026-10-03
13
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: AbstractRuntime
3
- Version: 0.8.5
3
+ Version: 0.9.1
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
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
22
  Requires-Python: >=3.10
23
- Requires-Dist: abstractcore>=2.24.0
23
+ Requires-Dist: abstractcore>=2.25.1
24
24
  Requires-Dist: abstractmemory>=0.3.0
25
25
  Requires-Dist: abstractsemantics>=0.0.5
26
26
  Requires-Dist: anyio<5.0.0,>=4.12.1
@@ -35,14 +35,14 @@ Requires-Dist: reportlab<5.0.0,>=4.0.0
35
35
  Requires-Dist: restrictedpython>=7.0
36
36
  Requires-Dist: unstructured[docx,odt,pptx,rtf,xlsx]<0.19.0,>=0.18.32
37
37
  Provides-Extra: apple
38
- Requires-Dist: abstractcore[apple]>=2.24.0; extra == 'apple'
38
+ Requires-Dist: abstractcore[apple]>=2.25.1; extra == 'apple'
39
39
  Requires-Dist: setuptools<82.0.0,>=80.10.2; extra == 'apple'
40
40
  Provides-Extra: docs
41
41
  Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
42
42
  Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
43
43
  Requires-Dist: pymdown-extensions>=10.0; extra == 'docs'
44
44
  Provides-Extra: gpu
45
- Requires-Dist: abstractcore[gpu]>=2.24.0; extra == 'gpu'
45
+ Requires-Dist: abstractcore[gpu]>=2.25.1; extra == 'gpu'
46
46
  Requires-Dist: setuptools<82.0.0,>=77.0.3; extra == 'gpu'
47
47
  Provides-Extra: test
48
48
  Requires-Dist: aiosmtpd<2.0.0,>=1.4.4; extra == 'test'
@@ -26,7 +26,7 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
26
26
  - `faq.md` — common questions (recommended)
27
27
  - `manual_testing.md` — manual smoke tests and how to run the test suite
28
28
  - `artifacts.md` — Runtime artifact identity, descriptors, provenance, catalog search, and access stats
29
- - `integrations/abstractcore.md` — wiring `LLM_CALL` / `TOOL_CALLS`, the `config_facade` models/engines/host-jobs passthroughs for hosts, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, model-residency listings, locks and model switching, live token streaming, workspace-scoped tools, durable bloc prompt-cache control, media inputs, generated media outputs, video progress events, and tool approval waits via AbstractCore
29
+ - `integrations/abstractcore.md` — wiring `LLM_CALL` / `TOOL_CALLS`, the `config_facade` models/engines/host-jobs passthroughs for hosts, the `structured_facade` response_format check for hosts, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, model-residency listings, locks and model switching, live token streaming, workspace-scoped tools, durable bloc prompt-cache control, media inputs, generated media outputs, video progress events, and tool approval waits via AbstractCore
30
30
  - `tools-comms.md` — enabling the optional comms toolset (email/WhatsApp/Telegram)
31
31
  - `email.md` — email for each user: run-scoped account binding and the host resolver, sending without asking (self and pre-authorised recipients), the durable event inbox and mail feeder, the `email.received@1` trigger, and the send-email action
32
32
  - `tool-approval.md` — tool risk tiers, the run-policy rank ceiling, and per-call refiners (the `send_email` recipient rule: self and pre-authorised recipients)
@@ -221,7 +221,7 @@ Deep dive: [automations.md](automations.md).
221
221
 
222
222
  ```python
223
223
  from abstractruntime.automations import (
224
- apply_automation_command, # pause / resume / run_now / revise / stop_current / archive
224
+ apply_automation_command, # pause / resume / run_now / revise / stop_current / archive / unarchive
225
225
  create_automation, # -> (automation_id, revision)
226
226
  drive_automation, # standalone run loop
227
227
  get_automation,
@@ -262,6 +262,7 @@ from abstractruntime.email import (
262
262
 
263
263
  - `Runtime.set_email_context_resolver(fn)`: `fn(binding, *, use) -> EmailContext | None` (`use` is `"agent_tool"` or `"action"`; `fn(binding)` also accepted), per runtime, memory only
264
264
  - `Runtime.set_email_binding(binding | None)` / `Runtime.email_binding`: the account occurrences are bound to
265
+ - `Runtime.set_occurrence_input_resolver(fn | None)` / `Runtime.occurrence_input_resolver`: `fn(definition, input_data) -> input_data`, called at each automation occurrence's admission (its run start) and frozen with the occurrence's inputs (a replayed dispatch stays identical); a non-dict answer fails the admission. The gateway re-resolves an automation's "Use my default" workspaces here. None (default): the definition's inputs as stored
265
266
  - `Runtime.set_event_inbox(inbox)` / `Runtime.event_inbox`: required by `email.received@1`
266
267
  - `EmailInboxFeeder(inbox, account_ref=...).poll(ctx, *, now=None, force=False) -> PollReport` and `.status()`
267
268
  - toolsets: `get_default_toolsets(..., email_enabled=True)` (also `list_default_tool_specs`, `build_default_tool_map`, `list_tool_catalog`); no env flag; `list_tool_catalog(email_enabled=False, email_off_reason="not_connected" | "admin_disabled" | "not_available" | "agent_tools_off")`
@@ -269,6 +270,7 @@ from abstractruntime.email import (
269
270
  - approval: the `send_email_recipient@v2` refiner ([tool-approval.md](tool-approval.md#per-call-refiners))
270
271
  - `adopt_legacy_schedule_projection(run)`: read-only summary of a legacy gateway `scheduled:*` root
271
272
  - read-only mounts: `_runtime.workspace_read_only_paths` (absolute folders; file write tools and VisualFlow writers refused inside, reads and command/code tools allowed); helpers `read_only_paths(vars)`, `path_is_read_only(vars, path)` and `READ_ONLY_PATHS_KEY` in `abstractruntime.utils.workspace_paths`
273
+ - writable exceptions inside read-only roots: `workspace_writable_paths` (top-level or `_runtime`; absolute folders). A path is read-only when a read-only root contains it and no writable path inside that root contains it, so the more specific rule wins (a host sets `/` read-only plus the run's folder and its read & write folders for a read-only default). Child runs and VisualFlow file nodes get the parent's exceptions exactly; a child never adds one. Helpers: `writable_paths(vars)`, `is_read_only_target(path, read_only_roots, writable_roots)`, `WRITABLE_PATHS_KEY`.
272
274
  - read-only workspaces: run vars `workspace_read_only: true` (or `_runtime.workspace_read_only: true`); `abstractruntime.integrations.abstractcore.tool_effects.TOOL_EFFECT_CLASSES` classifies every exposable tool as `read`, `write`, `exec`, `delegate`, `comms` or `memory-write`
273
275
 
274
276
  ## Sessions and history
@@ -395,3 +397,7 @@ This provides handlers for `MEMORY_KG_*` effects (opt-in wiring layer).
395
397
  ### Host ASGI serving
396
398
 
397
399
  `abstractruntime.integrations.abstractcore.server_facade.serve_core_request(scope, receive, send, *, token: str, allow_unauthenticated: bool = False)` delegates host-admitted ASGI requests with request-scoped Core authentication. See [host-managed serving](integrations/abstractcore.md#host-managed-serving) for network and credential responsibilities.
400
+
401
+ ### Structured-output checks
402
+
403
+ `abstractruntime.integrations.abstractcore.structured_facade.parse_response_format(raw) -> (kind, schema, name)` checks an OpenAI `response_format` and raises `ResponseFormatError` (AbstractCore's own class, with `.param`) for an unusable one. Both are also exported flat from `abstractruntime.integrations.abstractcore`. Requires AbstractCore 2.25.0 or newer. See [structured-output checks for hosts](integrations/abstractcore.md#structured-output-checks-for-hosts-structured-facade).
@@ -34,7 +34,7 @@ sources), `abstractruntime.automation_queries` (listing), `abstractruntime.sessi
34
34
  ```mermaid
35
35
  flowchart LR
36
36
  Trigger["Trigger source<br/>schedule@1 / manual@1"] -->|"due tick or run now"| Controller["Controller run<br/>(automation id)<br/>vars._meta.automation<br/>vars._runtime.automation"]
37
- Commands["apply_automation_command<br/>pause / resume / run_now /<br/>revise / stop_current / archive"] -->|"decision + wake"| Controller
37
+ Commands["apply_automation_command<br/>pause / resume / run_now /<br/>revise / stop_current / archive / unarchive"] -->|"decision + wake"| Controller
38
38
  Controller -->|"START_SUBWORKFLOW<br/>deterministic run_id"| Occurrence["Occurrence run<br/>role: occurrence<br/>(a session turn)"]
39
39
  Occurrence --> Descendants["Descendant runs<br/>role: descendant"]
40
40
  Occurrence -->|"output: answer, notify"| Controller
@@ -292,6 +292,7 @@ expected_revision=None, now=None)` is the only way to change an automation. It r
292
292
  | `automation.revise` | `payload.changes = {title?, target?, trigger?, context?, policy?}` (at least one). `title`, `target`, `trigger` and `context` are replaced whole; `policy` fields are merged, so a field you do not send keeps its value. The next revision applies from the controller's next step. A changed trigger gets a new binding and is re-armed after now, so no past tick fires; an unchanged trigger keeps its binding. | `invalid_state` when archived or finished; the definition's own reason codes for invalid changes |
293
293
  | `automation.stop_current` | Cancels the running occurrence tree, or its pending retry. The occurrence completes as `cancelled`, quietly. | `invalid_state` when nothing is running |
294
294
  | `automation.archive` | Stops further admissions; the current occurrence finishes and the controller then ends. History is kept and the automation stays listed. Archiving twice is an applied no-op. | — |
295
+ | `automation.unarchive` | Lifts the archive mark and brings the automation back **paused** (send `automation.resume` to re-arm its trigger). A controller that ended because it was archived restarts at `read_definition` and parks on its wake wait; occurrences, ledger and history are untouched. An exhausted or failed automation only loses the archive mark and keeps its status. Unarchiving an automation that is not archived is an applied no-op. | — |
295
296
 
296
297
  Every command can also be rejected with:
297
298
 
@@ -305,7 +306,7 @@ Commands are idempotent per `command_id`. A `command_id` is tied to its whole co
305
306
  `expected_revision`). The `automation.command_result` record, keyed
306
307
  `automation:command_result:<automation_id>:<command_id>`, is the decision. Sending the same command again returns the
307
308
  recorded result with `duplicate: true` and repeats only the follow-ups that are safe to repeat: the observation
308
- record (`automation.paused`, `automation.resumed`, `automation.revised`, `automation.archived`), waking the
309
+ record (`automation.paused`, `automation.resumed`, `automation.revised`, `automation.archived`, `automation.unarchived`), waking the
309
310
  controller, and cancelling the stopped child. A host that fails to carry out a command itself records the failure
310
311
  with `record_automation_command_result(...)`, passing the same `payload` and `expected_revision` so a later replay is
311
312
  recognized.
@@ -51,7 +51,9 @@ Docs: `getting-started.md`. Code: `src/abstractruntime/core/runtime.py`, `src/ab
51
51
  Create an automation. An automation is a durable controller run that starts the target workflow as a child run (an
52
52
  occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`) or `manual@1` (run now only).
53
53
  `create_automation(...)` creates it, `apply_automation_command(...)` pauses, resumes, runs now, edits, stops the
54
- current occurrence or archives it, and the host drives it like any run (`drive_automation` does this in-process).
54
+ current occurrence, archives it or unarchives it (it comes back paused with its history), and the host drives it
55
+ like any run (`drive_automation` does this in-process). Nothing is deleted: an archived automation keeps its
56
+ occurrences and history and stays listed with status `archived`.
55
57
 
56
58
  The `Scheduler` is different: it is a driver loop that resumes due waits of existing runs. It does not create runs.
57
59
 
@@ -97,9 +99,9 @@ Docs: `automations.md#tool-approval`, `automations.md#waits-on-a-person`.
97
99
 
98
100
  Not through its file tools. A discussion works in its own writable workspace and sees the automation's workspace as
99
101
  a read-only mount (`_runtime.workspace_read_only_paths`): file tools and VisualFlow writers that target a path inside
100
- the mount are refused, reads work. Commands and code (`execute_command`, `execute_python`) are allowed, because the
101
- shell cannot be sandboxed; a command can therefore still change files if it chooses to, so keep tool approval on for
102
- commands where that matters. Every later turn in the discussion session keeps the same setup, whoever starts it, and
102
+ the mount are refused, reads work. Commands and code (`execute_command`, `shell_exec`, `local_helper_start`,
103
+ AbstractAgent's `execute_python`) run inside an OS sandbox built from the same workspaces (macOS `sandbox-exec`, Linux
104
+ `bwrap`/Landlock), so they cannot write into the mount either; on a host with no sandbox they are refused. Every later turn in the discussion session keeps the same setup, whoever starts it, and
103
105
  the discussion never writes back into the automation's session, state or ledger.
104
106
 
105
107
  Docs: `automations.md#discussions`, `automations.md#read-only-mounts`.
@@ -494,16 +494,19 @@ When a run sets `workspace_root` in its vars, file tools (`read_file`, `write_fi
494
494
  | --- | --- |
495
495
  | `workspace_root` | Base folder for relative paths and the shell's starting folder. Relative roots resolve against `ABSTRACT_WORKSPACE_BASE_DIR` when set. |
496
496
  | `workspace_access_mode` | `workspace_only` (default: paths stay under the root), `workspace_or_allowed` (also under `workspace_allowed_paths`), or `all_except_ignored` (anywhere except `workspace_ignored_paths`). |
497
- | `workspace_allowed_paths` | Extra folders a `workspace_or_allowed` run may use. |
498
- | `workspace_ignored_paths` | The operator's exclusions; always refused. |
497
+ | `workspace_allowed_paths` | Additional workspaces a `workspace_or_allowed` run may use. |
498
+ | `workspace_ignored_paths` | Refused workspaces. A more specific allowed workspace inside one stays reachable (see *Nesting* below). |
499
499
  | `workspace_builtin_deny_prefixes` | The host's own protected folders (for example a gateway's data folder and credential folders), as path prefixes. Anything under one is refused. |
500
500
  | `workspace_builtin_allow` | Exceptions inside the host's protected folders (for example the run's own folder inside the data folder). The operator's `workspace_ignored_paths` still win over them. |
501
+ | `workspace_read_only_paths` / `workspace_writable_paths` | Read-only roots and the writable exceptions inside them (`"/"` = a read-only default). The more specific rule wins. |
501
502
 
502
503
  Lists accept a JSON array, a JSON array pasted as a string, or newline-separated entries.
503
504
 
504
- - When an `LLM_CALL` offers tools and the run has a workspace scope, the runtime appends a short description of the scope to the system prompt: the root, the access mode, the authorized roots and the operator's `workspace_ignored_paths`. The host's built-in deny prefixes and allow entries are enforced but never described to the model, so the system prompt stays identical from turn to turn while the host's folders change, and the prompt cache stays warm. A refused path is reported as `Path is not accessible (protected by the host)` without listing the host's rules.
505
- - Child runs (subworkflows and agent delegation) inherit all six vars unless they set their own; VisualFlow file and document nodes (`read_file`, `write_file`, `read_pdf`, `write_pdf`, `write_docx`, `write_chart`) apply the same scope.
506
- - Shell tools are pinned to their starting folder only. A command can still reach other paths (`cd ..`, absolute paths); the workspace scope is a file-tool policy, not a sandbox.
505
+ - When an `LLM_CALL` offers tools and the run has a workspace scope, the runtime appends a short description of the scope to the system prompt: the root (the run's default working directory); each allowed workspace outside the root with its mode (`(read-only)` or `(read & write)`, from `workspace_read_only_paths` and `workspace_writable_paths`); under `all_except_ignored` the mode of everything else (`Everything else: (read-only)`); the access mode; the authorized roots and the operator's `workspace_ignored_paths`. The host's built-in deny prefixes and allow entries are enforced but never described to the model, so the system prompt stays identical from turn to turn while the host's folders change, and the prompt cache stays warm. A refused path is reported as `Path is not accessible (protected by the host)` without listing the host's rules.
506
+ - Child runs (subworkflows and agent delegation) inherit the workspace vars unless they set their own; VisualFlow file and document nodes (`read_file`, `write_file`, `read_pdf`, `write_pdf`, `write_docx`, `write_chart`) apply the same scope.
507
+ - **Nesting (most specific row wins).** For a path P (symlinks resolved), the candidates are `workspace_root` (read & write), `workspace_allowed_paths` (not under `workspace_only`) and `workspace_ignored_paths`. The longest candidate that contains P decides: a refused entry refuses, the root or an allowed entry allows; a tie between a refused entry and an allowed one (or the root) at the same path refuses; no candidate falls back to the access mode (`all_except_ignored` allows, the others refuse). The host's built-in protection is absolute: under a `workspace_builtin_deny_prefixes` entry and not under a `workspace_builtin_allow` entry is refused whatever the rows say. So refusing `/Users/me` and allowing `/Users/me/project` makes the project reachable and the rest of `/Users/me` refused; a refused folder inside an allowed one refuses that subtree. AbstractGateway applies the same rule when it validates and computes a run's workspaces.
508
+ - **Command sandbox.** `execute_command`, `shell_exec` (the whole persistent session), `local_helper_start` and AbstractAgent's `execute_python` (0.3.18 or newer) start in the workspace and run inside an OS sandbox built from the SAME scope (`sandbox_stamp(scope)`, stamped on every call as the hidden `_sandbox` argument; a model- or payload-supplied value is always replaced). AbstractCore (`abstractcore.tools.sandbox`) applies it: macOS `sandbox-exec`, Linux `bwrap`, or Linux Landlock for "Deny everything, allow listed workspaces". Mapping: `all_except_ignored` → "Allow everything, refuse listed workspaces" (`any_except_denied`), otherwise "Deny everything, allow listed workspaces" (`allowed_only`); a `"/"` read-only root → read-only default; each allowed workspace with its mode; refused paths and the built-in protection as they are. The command string is never parsed — `cd ..`, absolute paths, `$(…)`, symlinks and scripts are stopped by the kernel. With no sandbox on the host, or an AbstractCore without `abstractcore.tools.sandbox`, the command is refused with one sentence and the run continues. The entity exec tool runs inside a sandbox limited to the entity's workspace and its whitelisted mounts. The tool result carries `sandbox: {kind, …}` and a `Sandbox: …` line; the stamp rides the tool call in the run's evidence. Hosts set the host policy (the scrubbed environment commands start from, and whether unsandboxed commands are allowed on a host with no sandbox) once at boot through `abstractruntime.integrations.abstractcore.command_sandbox_host` (`configure_host`, `host_policy`, `host_sandbox_kind`), never by importing AbstractCore.
509
+ - **Browser probe.** A local `browser_probe` target (a path or a `file://` URL) is walled like `read_file`'s path and carries the same `_sandbox` stamp: AbstractCore 2.25.1 serves the page to the browser from a loopback origin that answers only for files this scope can read (never `file://`). Remote `http(s)://` targets carry no stamp.
507
510
 
508
511
  ## Prompt-cache control plane and durable blocs
509
512
 
@@ -1046,8 +1049,14 @@ Public durable entry points:
1046
1049
  These helpers create child runs under an existing parent run and execute the real
1047
1050
  `LLM_CALL`, `TOOL_CALLS`, or stream finalization through Runtime rather than
1048
1051
  doing external work in host/controller code. `stream_voice(...)` yields TTS
1049
- stream events for progressive playback and completes the child run with the
1050
- final audio artifact when the stream succeeds.
1052
+ stream events for progressive playback; it is never a wait: nothing durable
1053
+ exists while audio streams, and when the stream ends (done, error, cancel or
1054
+ the consumer closing it) the child run is created already completed with the
1055
+ outcome (the final audio artifact on success). The child's id is announced up
1056
+ front in the `runtime_start` event (`child_run_id`). A host that finds a
1057
+ streamed-speech wait left by a runtime before this behaviour
1058
+ (`is_interrupted_voice_stream_wait`) closes it with
1059
+ `close_interrupted_voice_stream(child_run_id, reason=...)`.
1051
1060
 
1052
1061
  Example:
1053
1062
 
@@ -1184,3 +1193,18 @@ Provide a nonempty token even for open access: absent Authorization is allowed w
1184
1193
  Anonymous callers cannot use server-held cloud credentials; explicit provider
1185
1194
  keys use `X-AbstractCore-Provider-API-Key`. This serving facade does not create
1186
1195
  durable Runtime runs. The AbstractCore server dependencies must be installed.
1196
+
1197
+ ## Structured-output checks for hosts (structured facade)
1198
+
1199
+ A host that accepts an OpenAI `response_format` checks it before any model sees it with
1200
+ `abstractruntime.integrations.abstractcore.structured_facade` (also exported flat from
1201
+ `abstractruntime.integrations.abstractcore`):
1202
+
1203
+ - `parse_response_format(raw)` returns `(kind, schema, name)`, where kind is `"text"`,
1204
+ `"json_object"` or `"json_schema"` and schema is `None` unless kind is `"json_schema"`.
1205
+ - `ResponseFormatError` is AbstractCore's own error class, so `except ResponseFormatError`
1206
+ catches exactly what Core raises; `.param` names the offending field
1207
+ (`"response_format"` or a nested name such as `"response_format.type"`).
1208
+
1209
+ AbstractCore is imported on first use; it needs AbstractCore 2.25.0 or newer. AbstractGateway's
1210
+ `/v1/chat/completions` uses this facade, so the gateway never imports AbstractCore itself.
@@ -1086,7 +1086,7 @@ Deep dive: [automations.md](automations.md).
1086
1086
 
1087
1087
  ```python
1088
1088
  from abstractruntime.automations import (
1089
- apply_automation_command, # pause / resume / run_now / revise / stop_current / archive
1089
+ apply_automation_command, # pause / resume / run_now / revise / stop_current / archive / unarchive
1090
1090
  create_automation, # -> (automation_id, revision)
1091
1091
  drive_automation, # standalone run loop
1092
1092
  get_automation,
@@ -1127,6 +1127,7 @@ from abstractruntime.email import (
1127
1127
 
1128
1128
  - `Runtime.set_email_context_resolver(fn)`: `fn(binding, *, use) -> EmailContext | None` (`use` is `"agent_tool"` or `"action"`; `fn(binding)` also accepted), per runtime, memory only
1129
1129
  - `Runtime.set_email_binding(binding | None)` / `Runtime.email_binding`: the account occurrences are bound to
1130
+ - `Runtime.set_occurrence_input_resolver(fn | None)` / `Runtime.occurrence_input_resolver`: `fn(definition, input_data) -> input_data`, called at each automation occurrence's admission (its run start) and frozen with the occurrence's inputs (a replayed dispatch stays identical); a non-dict answer fails the admission. The gateway re-resolves an automation's "Use my default" workspaces here. None (default): the definition's inputs as stored
1130
1131
  - `Runtime.set_event_inbox(inbox)` / `Runtime.event_inbox`: required by `email.received@1`
1131
1132
  - `EmailInboxFeeder(inbox, account_ref=...).poll(ctx, *, now=None, force=False) -> PollReport` and `.status()`
1132
1133
  - toolsets: `get_default_toolsets(..., email_enabled=True)` (also `list_default_tool_specs`, `build_default_tool_map`, `list_tool_catalog`); no env flag; `list_tool_catalog(email_enabled=False, email_off_reason="not_connected" | "admin_disabled" | "not_available" | "agent_tools_off")`
@@ -1134,6 +1135,7 @@ from abstractruntime.email import (
1134
1135
  - approval: the `send_email_recipient@v2` refiner ([tool-approval.md](tool-approval.md#per-call-refiners))
1135
1136
  - `adopt_legacy_schedule_projection(run)`: read-only summary of a legacy gateway `scheduled:*` root
1136
1137
  - read-only mounts: `_runtime.workspace_read_only_paths` (absolute folders; file write tools and VisualFlow writers refused inside, reads and command/code tools allowed); helpers `read_only_paths(vars)`, `path_is_read_only(vars, path)` and `READ_ONLY_PATHS_KEY` in `abstractruntime.utils.workspace_paths`
1138
+ - writable exceptions inside read-only roots: `workspace_writable_paths` (top-level or `_runtime`; absolute folders). A path is read-only when a read-only root contains it and no writable path inside that root contains it, so the more specific rule wins (a host sets `/` read-only plus the run's folder and its read & write folders for a read-only default). Child runs and VisualFlow file nodes get the parent's exceptions exactly; a child never adds one. Helpers: `writable_paths(vars)`, `is_read_only_target(path, read_only_roots, writable_roots)`, `WRITABLE_PATHS_KEY`.
1137
1139
  - read-only workspaces: run vars `workspace_read_only: true` (or `_runtime.workspace_read_only: true`); `abstractruntime.integrations.abstractcore.tool_effects.TOOL_EFFECT_CLASSES` classifies every exposable tool as `read`, `write`, `exec`, `delegate`, `comms` or `memory-write`
1138
1140
 
1139
1141
  ## Sessions and history
@@ -1261,6 +1263,10 @@ This provides handlers for `MEMORY_KG_*` effects (opt-in wiring layer).
1261
1263
 
1262
1264
  `abstractruntime.integrations.abstractcore.server_facade.serve_core_request(scope, receive, send, *, token: str, allow_unauthenticated: bool = False)` delegates host-admitted ASGI requests with request-scoped Core authentication. See [host-managed serving](integrations/abstractcore.md#host-managed-serving) for network and credential responsibilities.
1263
1265
 
1266
+ ### Structured-output checks
1267
+
1268
+ `abstractruntime.integrations.abstractcore.structured_facade.parse_response_format(raw) -> (kind, schema, name)` checks an OpenAI `response_format` and raises `ResponseFormatError` (AbstractCore's own class, with `.param`) for an unusable one. Both are also exported flat from `abstractruntime.integrations.abstractcore`. Requires AbstractCore 2.25.0 or newer. See [structured-output checks for hosts](integrations/abstractcore.md#structured-output-checks-for-hosts-structured-facade).
1269
+
1264
1270
 
1265
1271
  ==============================================================================
1266
1272
  # FILE: docs/faq.md
@@ -1319,7 +1325,9 @@ Docs: `getting-started.md`. Code: `src/abstractruntime/core/runtime.py`, `src/ab
1319
1325
  Create an automation. An automation is a durable controller run that starts the target workflow as a child run (an
1320
1326
  occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`) or `manual@1` (run now only).
1321
1327
  `create_automation(...)` creates it, `apply_automation_command(...)` pauses, resumes, runs now, edits, stops the
1322
- current occurrence or archives it, and the host drives it like any run (`drive_automation` does this in-process).
1328
+ current occurrence, archives it or unarchives it (it comes back paused with its history), and the host drives it
1329
+ like any run (`drive_automation` does this in-process). Nothing is deleted: an archived automation keeps its
1330
+ occurrences and history and stays listed with status `archived`.
1323
1331
 
1324
1332
  The `Scheduler` is different: it is a driver loop that resumes due waits of existing runs. It does not create runs.
1325
1333
 
@@ -1365,9 +1373,9 @@ Docs: `automations.md#tool-approval`, `automations.md#waits-on-a-person`.
1365
1373
 
1366
1374
  Not through its file tools. A discussion works in its own writable workspace and sees the automation's workspace as
1367
1375
  a read-only mount (`_runtime.workspace_read_only_paths`): file tools and VisualFlow writers that target a path inside
1368
- the mount are refused, reads work. Commands and code (`execute_command`, `execute_python`) are allowed, because the
1369
- shell cannot be sandboxed; a command can therefore still change files if it chooses to, so keep tool approval on for
1370
- commands where that matters. Every later turn in the discussion session keeps the same setup, whoever starts it, and
1376
+ the mount are refused, reads work. Commands and code (`execute_command`, `shell_exec`, `local_helper_start`,
1377
+ AbstractAgent's `execute_python`) run inside an OS sandbox built from the same workspaces (macOS `sandbox-exec`, Linux
1378
+ `bwrap`/Landlock), so they cannot write into the mount either; on a host with no sandbox they are refused. Every later turn in the discussion session keeps the same setup, whoever starts it, and
1371
1379
  the discussion never writes back into the automation's session, state or ledger.
1372
1380
 
1373
1381
  Docs: `automations.md#discussions`, `automations.md#read-only-mounts`.
@@ -2460,16 +2468,19 @@ When a run sets `workspace_root` in its vars, file tools (`read_file`, `write_fi
2460
2468
  | --- | --- |
2461
2469
  | `workspace_root` | Base folder for relative paths and the shell's starting folder. Relative roots resolve against `ABSTRACT_WORKSPACE_BASE_DIR` when set. |
2462
2470
  | `workspace_access_mode` | `workspace_only` (default: paths stay under the root), `workspace_or_allowed` (also under `workspace_allowed_paths`), or `all_except_ignored` (anywhere except `workspace_ignored_paths`). |
2463
- | `workspace_allowed_paths` | Extra folders a `workspace_or_allowed` run may use. |
2464
- | `workspace_ignored_paths` | The operator's exclusions; always refused. |
2471
+ | `workspace_allowed_paths` | Additional workspaces a `workspace_or_allowed` run may use. |
2472
+ | `workspace_ignored_paths` | Refused workspaces. A more specific allowed workspace inside one stays reachable (see *Nesting* below). |
2465
2473
  | `workspace_builtin_deny_prefixes` | The host's own protected folders (for example a gateway's data folder and credential folders), as path prefixes. Anything under one is refused. |
2466
2474
  | `workspace_builtin_allow` | Exceptions inside the host's protected folders (for example the run's own folder inside the data folder). The operator's `workspace_ignored_paths` still win over them. |
2475
+ | `workspace_read_only_paths` / `workspace_writable_paths` | Read-only roots and the writable exceptions inside them (`"/"` = a read-only default). The more specific rule wins. |
2467
2476
 
2468
2477
  Lists accept a JSON array, a JSON array pasted as a string, or newline-separated entries.
2469
2478
 
2470
- - When an `LLM_CALL` offers tools and the run has a workspace scope, the runtime appends a short description of the scope to the system prompt: the root, the access mode, the authorized roots and the operator's `workspace_ignored_paths`. The host's built-in deny prefixes and allow entries are enforced but never described to the model, so the system prompt stays identical from turn to turn while the host's folders change, and the prompt cache stays warm. A refused path is reported as `Path is not accessible (protected by the host)` without listing the host's rules.
2471
- - Child runs (subworkflows and agent delegation) inherit all six vars unless they set their own; VisualFlow file and document nodes (`read_file`, `write_file`, `read_pdf`, `write_pdf`, `write_docx`, `write_chart`) apply the same scope.
2472
- - Shell tools are pinned to their starting folder only. A command can still reach other paths (`cd ..`, absolute paths); the workspace scope is a file-tool policy, not a sandbox.
2479
+ - When an `LLM_CALL` offers tools and the run has a workspace scope, the runtime appends a short description of the scope to the system prompt: the root (the run's default working directory); each allowed workspace outside the root with its mode (`(read-only)` or `(read & write)`, from `workspace_read_only_paths` and `workspace_writable_paths`); under `all_except_ignored` the mode of everything else (`Everything else: (read-only)`); the access mode; the authorized roots and the operator's `workspace_ignored_paths`. The host's built-in deny prefixes and allow entries are enforced but never described to the model, so the system prompt stays identical from turn to turn while the host's folders change, and the prompt cache stays warm. A refused path is reported as `Path is not accessible (protected by the host)` without listing the host's rules.
2480
+ - Child runs (subworkflows and agent delegation) inherit the workspace vars unless they set their own; VisualFlow file and document nodes (`read_file`, `write_file`, `read_pdf`, `write_pdf`, `write_docx`, `write_chart`) apply the same scope.
2481
+ - **Nesting (most specific row wins).** For a path P (symlinks resolved), the candidates are `workspace_root` (read & write), `workspace_allowed_paths` (not under `workspace_only`) and `workspace_ignored_paths`. The longest candidate that contains P decides: a refused entry refuses, the root or an allowed entry allows; a tie between a refused entry and an allowed one (or the root) at the same path refuses; no candidate falls back to the access mode (`all_except_ignored` allows, the others refuse). The host's built-in protection is absolute: under a `workspace_builtin_deny_prefixes` entry and not under a `workspace_builtin_allow` entry is refused whatever the rows say. So refusing `/Users/me` and allowing `/Users/me/project` makes the project reachable and the rest of `/Users/me` refused; a refused folder inside an allowed one refuses that subtree. AbstractGateway applies the same rule when it validates and computes a run's workspaces.
2482
+ - **Command sandbox.** `execute_command`, `shell_exec` (the whole persistent session), `local_helper_start` and AbstractAgent's `execute_python` (0.3.18 or newer) start in the workspace and run inside an OS sandbox built from the SAME scope (`sandbox_stamp(scope)`, stamped on every call as the hidden `_sandbox` argument; a model- or payload-supplied value is always replaced). AbstractCore (`abstractcore.tools.sandbox`) applies it: macOS `sandbox-exec`, Linux `bwrap`, or Linux Landlock for "Deny everything, allow listed workspaces". Mapping: `all_except_ignored` → "Allow everything, refuse listed workspaces" (`any_except_denied`), otherwise "Deny everything, allow listed workspaces" (`allowed_only`); a `"/"` read-only root → read-only default; each allowed workspace with its mode; refused paths and the built-in protection as they are. The command string is never parsed — `cd ..`, absolute paths, `$(…)`, symlinks and scripts are stopped by the kernel. With no sandbox on the host, or an AbstractCore without `abstractcore.tools.sandbox`, the command is refused with one sentence and the run continues. The entity exec tool runs inside a sandbox limited to the entity's workspace and its whitelisted mounts. The tool result carries `sandbox: {kind, …}` and a `Sandbox: …` line; the stamp rides the tool call in the run's evidence. Hosts set the host policy (the scrubbed environment commands start from, and whether unsandboxed commands are allowed on a host with no sandbox) once at boot through `abstractruntime.integrations.abstractcore.command_sandbox_host` (`configure_host`, `host_policy`, `host_sandbox_kind`), never by importing AbstractCore.
2483
+ - **Browser probe.** A local `browser_probe` target (a path or a `file://` URL) is walled like `read_file`'s path and carries the same `_sandbox` stamp: AbstractCore 2.25.1 serves the page to the browser from a loopback origin that answers only for files this scope can read (never `file://`). Remote `http(s)://` targets carry no stamp.
2473
2484
 
2474
2485
  ## Prompt-cache control plane and durable blocs
2475
2486
 
@@ -3012,8 +3023,14 @@ Public durable entry points:
3012
3023
  These helpers create child runs under an existing parent run and execute the real
3013
3024
  `LLM_CALL`, `TOOL_CALLS`, or stream finalization through Runtime rather than
3014
3025
  doing external work in host/controller code. `stream_voice(...)` yields TTS
3015
- stream events for progressive playback and completes the child run with the
3016
- final audio artifact when the stream succeeds.
3026
+ stream events for progressive playback; it is never a wait: nothing durable
3027
+ exists while audio streams, and when the stream ends (done, error, cancel or
3028
+ the consumer closing it) the child run is created already completed with the
3029
+ outcome (the final audio artifact on success). The child's id is announced up
3030
+ front in the `runtime_start` event (`child_run_id`). A host that finds a
3031
+ streamed-speech wait left by a runtime before this behaviour
3032
+ (`is_interrupted_voice_stream_wait`) closes it with
3033
+ `close_interrupted_voice_stream(child_run_id, reason=...)`.
3017
3034
 
3018
3035
  Example:
3019
3036
 
@@ -3151,6 +3168,21 @@ Anonymous callers cannot use server-held cloud credentials; explicit provider
3151
3168
  keys use `X-AbstractCore-Provider-API-Key`. This serving facade does not create
3152
3169
  durable Runtime runs. The AbstractCore server dependencies must be installed.
3153
3170
 
3171
+ ## Structured-output checks for hosts (structured facade)
3172
+
3173
+ A host that accepts an OpenAI `response_format` checks it before any model sees it with
3174
+ `abstractruntime.integrations.abstractcore.structured_facade` (also exported flat from
3175
+ `abstractruntime.integrations.abstractcore`):
3176
+
3177
+ - `parse_response_format(raw)` returns `(kind, schema, name)`, where kind is `"text"`,
3178
+ `"json_object"` or `"json_schema"` and schema is `None` unless kind is `"json_schema"`.
3179
+ - `ResponseFormatError` is AbstractCore's own error class, so `except ResponseFormatError`
3180
+ catches exactly what Core raises; `.param` names the offending field
3181
+ (`"response_format"` or a nested name such as `"response_format.type"`).
3182
+
3183
+ AbstractCore is imported on first use; it needs AbstractCore 2.25.0 or newer. AbstractGateway's
3184
+ `/v1/chat/completions` uses this facade, so the gateway never imports AbstractCore itself.
3185
+
3154
3186
 
3155
3187
  ==============================================================================
3156
3188
  # FILE: docs/proposal.md
@@ -3575,7 +3607,7 @@ sources), `abstractruntime.automation_queries` (listing), `abstractruntime.sessi
3575
3607
  ```mermaid
3576
3608
  flowchart LR
3577
3609
  Trigger["Trigger source<br/>schedule@1 / manual@1"] -->|"due tick or run now"| Controller["Controller run<br/>(automation id)<br/>vars._meta.automation<br/>vars._runtime.automation"]
3578
- Commands["apply_automation_command<br/>pause / resume / run_now /<br/>revise / stop_current / archive"] -->|"decision + wake"| Controller
3610
+ Commands["apply_automation_command<br/>pause / resume / run_now /<br/>revise / stop_current / archive / unarchive"] -->|"decision + wake"| Controller
3579
3611
  Controller -->|"START_SUBWORKFLOW<br/>deterministic run_id"| Occurrence["Occurrence run<br/>role: occurrence<br/>(a session turn)"]
3580
3612
  Occurrence --> Descendants["Descendant runs<br/>role: descendant"]
3581
3613
  Occurrence -->|"output: answer, notify"| Controller
@@ -3833,6 +3865,7 @@ expected_revision=None, now=None)` is the only way to change an automation. It r
3833
3865
  | `automation.revise` | `payload.changes = {title?, target?, trigger?, context?, policy?}` (at least one). `title`, `target`, `trigger` and `context` are replaced whole; `policy` fields are merged, so a field you do not send keeps its value. The next revision applies from the controller's next step. A changed trigger gets a new binding and is re-armed after now, so no past tick fires; an unchanged trigger keeps its binding. | `invalid_state` when archived or finished; the definition's own reason codes for invalid changes |
3834
3866
  | `automation.stop_current` | Cancels the running occurrence tree, or its pending retry. The occurrence completes as `cancelled`, quietly. | `invalid_state` when nothing is running |
3835
3867
  | `automation.archive` | Stops further admissions; the current occurrence finishes and the controller then ends. History is kept and the automation stays listed. Archiving twice is an applied no-op. | — |
3868
+ | `automation.unarchive` | Lifts the archive mark and brings the automation back **paused** (send `automation.resume` to re-arm its trigger). A controller that ended because it was archived restarts at `read_definition` and parks on its wake wait; occurrences, ledger and history are untouched. An exhausted or failed automation only loses the archive mark and keeps its status. Unarchiving an automation that is not archived is an applied no-op. | — |
3836
3869
 
3837
3870
  Every command can also be rejected with:
3838
3871
 
@@ -3846,7 +3879,7 @@ Commands are idempotent per `command_id`. A `command_id` is tied to its whole co
3846
3879
  `expected_revision`). The `automation.command_result` record, keyed
3847
3880
  `automation:command_result:<automation_id>:<command_id>`, is the decision. Sending the same command again returns the
3848
3881
  recorded result with `duplicate: true` and repeats only the follow-ups that are safe to repeat: the observation
3849
- record (`automation.paused`, `automation.resumed`, `automation.revised`, `automation.archived`), waking the
3882
+ record (`automation.paused`, `automation.resumed`, `automation.revised`, `automation.archived`, `automation.unarchived`), waking the
3850
3883
  controller, and cancelling the stopped child. A host that fails to carry out a command itself records the failure
3851
3884
  with `record_automation_command_result(...)`, passing the same `payload` and `expected_revision` so a later replay is
3852
3885
  recognized.
@@ -5851,7 +5884,7 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
5851
5884
  - `faq.md` — common questions (recommended)
5852
5885
  - `manual_testing.md` — manual smoke tests and how to run the test suite
5853
5886
  - `artifacts.md` — Runtime artifact identity, descriptors, provenance, catalog search, and access stats
5854
- - `integrations/abstractcore.md` — wiring `LLM_CALL` / `TOOL_CALLS`, the `config_facade` models/engines/host-jobs passthroughs for hosts, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, model-residency listings, locks and model switching, live token streaming, workspace-scoped tools, durable bloc prompt-cache control, media inputs, generated media outputs, video progress events, and tool approval waits via AbstractCore
5887
+ - `integrations/abstractcore.md` — wiring `LLM_CALL` / `TOOL_CALLS`, the `config_facade` models/engines/host-jobs passthroughs for hosts, the `structured_facade` response_format check for hosts, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, model-residency listings, locks and model switching, live token streaming, workspace-scoped tools, durable bloc prompt-cache control, media inputs, generated media outputs, video progress events, and tool approval waits via AbstractCore
5855
5888
  - `tools-comms.md` — enabling the optional comms toolset (email/WhatsApp/Telegram)
5856
5889
  - `email.md` — email for each user: run-scoped account binding and the host resolver, sending without asking (self and pre-authorised recipients), the durable event inbox and mail feeder, the `email.received@1` trigger, and the send-email action
5857
5890
  - `tool-approval.md` — tool risk tiers, the run-policy rank ceiling, and per-call refiners (the `send_email` recipient rule: self and pre-authorised recipients)
@@ -3,7 +3,7 @@
3
3
  > Durable workflow runtime (interrupt → checkpoint → resume) with an append-only execution ledger.
4
4
 
5
5
  - Python: 3.10+ (see `pyproject.toml`)
6
- - Version: 0.8.5
6
+ - Version: 0.9.1
7
7
  - Ecosystem: [AbstractFramework](https://github.com/lpalbou/AbstractFramework) umbrella, integrates with [AbstractCore](https://github.com/lpalbou/abstractcore)
8
8
  - Hard invariant: `RunState.vars` must be JSON-serializable (`src/abstractruntime/core/models.py`)
9
9
  - Current AbstractCore baseline: base `abstractruntime` requires AbstractCore 2.24.0 or newer with its light install (remote providers, tools and the MCP worker, media routing); `abstractruntime[apple]` and `abstractruntime[gpu]` require AbstractCore's `apple` and `gpu` settings (`pyproject.toml`)
@@ -39,7 +39,7 @@
39
39
  - [Cancellation, pause and tool ceiling](docs/api.md#runtime-start--tick--resume): `Runtime.cancel_run(...)` stops the in-flight effect (recorded `cancelled`, never retried), a model unload cancels the calls using it first, `tick(..., step_gate=...)` pauses at step boundaries, and an explicit `allowed_tools` list is a run-tree ceiling approval policy cannot widen.
40
40
  - [Live token streaming](docs/integrations/abstractcore.md#live-token-streaming): `Runtime.set_live_delta_sink(sink)` plus run input `_runtime.stream: true` delivers `llm.delta` / `llm.delta_end` events (content and reasoning channels, `parent_run_id`) while an answer is generated; nothing reaches the ledger, children inherit the switch, and every call that cannot stream with a complete record says why (`reason: unavailable` + `detail`).
41
41
  - [Unloading and switching models](docs/integrations/abstractcore.md#unloading-and-switching-models): a default switch unloads the previous in-process model (MLX, HuggingFace, embeddings) unless another owner in the process claims it (pool, override, lock, building, default); a model still generating is unloaded when its call ends; diagnostics `pending_ejects` / `last_switch_ejects`; any listed row unloads by `runtime_id` (`local:<task>:<provider>:<model>`, including `local:embedding:<provider>:<model>`); `ttl_s` / `keep_alive` on in-process or already-loaded models are reported under `unsupported_options`.
42
- - [Workspace-scoped tools](docs/integrations/abstractcore.md#workspace-scoped-tools): `workspace_root`, `workspace_access_mode`, `workspace_allowed_paths`, `workspace_ignored_paths`, and the host-only `workspace_builtin_deny_prefixes` / `workspace_builtin_allow` (enforced, never shown to the model) scope file and shell tools; child runs inherit them.
42
+ - [Workspace-scoped tools](docs/integrations/abstractcore.md#workspace-scoped-tools): `workspace_root`, `workspace_access_mode`, `workspace_allowed_paths`, `workspace_ignored_paths`, and the host-only `workspace_builtin_deny_prefixes` / `workspace_builtin_allow` (enforced, never shown to the model) scope file and shell tools; the most specific row wins (longest real-path prefix, a refusal wins a tie, built-ins absolute); `execute_command`/`shell_exec`/`local_helper_start`/`execute_python` get the same set stamped as the hidden `_sandbox` arg and run inside AbstractCore's OS sandbox (refused when the host has none); child runs inherit them.
43
43
  - [Execution controls](docs/integrations/abstractcore.md#execution-controls-and-local-concurrency): inherited run/node MTP controls, scoped Core defaults, actual-host execution discovery, instance-aware scheduling, per-response outcomes and cache-group batching limits.
44
44
 
45
45
  - [AbstractCore integration](docs/integrations/abstractcore.md): `LLM_CALL` / `TOOL_CALLS` / `MODEL_RESIDENCY`, local/remote/hybrid, prompt-cache and residency host controls, host memory snapshots and per-session prompt-cache listing/clearing, host-wide provider-server rows in residency listings, model-residency locks (residency-required: locking a non-resident pair refuses with `model_not_resident`; unlock never requires residency) with `force`-gated unload and context-estimate relays, modality/host-identity fields and truthful `pinned`-aliases-`locked` lock state on local residency rows, local-only prompt-cache export/import admin, durable bloc/KV prompt-cache controls, discovery snapshot queries including `list_provider_models(..., capability_route=...)` and `list_vision_adapters(...)`, durable run-scoped image/edit-image/upscale-image/text-to-video/image-to-video/voice/streamed-voice/music/STT execution, batch `count`/`n`, `seeds`, ordered `lora_adapters`, video `flow_shift`, media inputs, generated media outputs, progress ledger events, provider-key headers, host endpoint-profile resolver hooks, and tool approval waits
@@ -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): 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
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, unarchive — back paused with its history, nothing deleted; 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.5"
7
+ version = "0.9.1"
8
8
  description = "AbstractRuntime: a durable graph runner designed to pair with AbstractCore."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -53,7 +53,9 @@ dependencies = [
53
53
  # plugins) without selecting local inference engines. 2.19.2 floors
54
54
  # abstractvision>=0.3.33, whose resident loads report `loaded_new` and whose
55
55
  # unload frees the pipeline (the resident media path relies on both).
56
- "abstractcore>=2.24.0",
56
+ # 2.25.1: the Linux bwrap profile binds an allowed child of a refused folder,
57
+ # and browser_probe takes the _sandbox stamp (scoped loopback origin).
58
+ "abstractcore>=2.25.1",
57
59
  "openai<3.0.0,>=1.109.1",
58
60
  "httpx<1.0.0,>=0.28.1",
59
61
  "anyio<5.0.0,>=4.12.1",
@@ -70,12 +72,12 @@ dependencies = [
70
72
 
71
73
  [project.optional-dependencies]
72
74
  apple = [
73
- "abstractcore[apple]>=2.24.0",
75
+ "abstractcore[apple]>=2.25.1",
74
76
  "setuptools<82.0.0,>=80.10.2",
75
77
  ]
76
78
 
77
79
  gpu = [
78
- "abstractcore[gpu]>=2.24.0",
80
+ "abstractcore[gpu]>=2.25.1",
79
81
  # vLLM 0.9-0.19 caps setuptools below 80; 77.0.3 is still a modern floor.
80
82
  "setuptools<82.0.0,>=77.0.3",
81
83
  ]
@@ -0,0 +1,12 @@
1
+ ### Security
2
+
3
+ - `browser_probe`: a local target (path or `file://` URL) now carries the run's `_sandbox` stamp, the same scope the commands get. AbstractCore 2.25.1 serves the page from a loopback origin limited to that scope instead of `file://`, so a page cannot load refused files as subresources. Needs AbstractCore 2.25.1 (an older `browser_probe` refuses the unknown argument and runs nothing). Test: `tests/test_browser_probe_target_walling.py`.
4
+
5
+ ### Fixed
6
+
7
+ - `stream_voice(...)` is never a wait. It used to start the child run parked on `WAIT_EVENT abstractcore.voice.tts.stream:<uuid>` for the whole stream: hosts folded that waiting record into the CALLER'S run (a Read aloud during a live turn read as "Waiting for an event"), and a host that died mid-stream left the child waiting forever. Now nothing durable exists while audio streams; when the stream ends (done, error, cancel or the consumer closing it) the child run is created already COMPLETED with the outcome. Its id is allocated up front: `runtime_start` carries it as `child_run_id` (schema `abstractruntime.tts_stream.start.v2`, no `wait_key`), as does the trace metadata. A stream cut by a crash leaves no run.
8
+ - `AbstractCoreRunFacade.close_interrupted_voice_stream(child_run_id, *, reason)` finishes a legacy streamed-speech wait left by an older process (completed, `errors[0] = {"code": "interrupted", "message": reason}`); `is_interrupted_voice_stream_wait(waiting)` and `LEGACY_VOICE_STREAM_WAIT_KEY_PREFIX` recognise one (exported from `integrations.abstractcore`). AbstractGateway calls it at startup.
9
+
10
+ ### Changed
11
+
12
+ - Requires AbstractCore 2.25.1 or newer (`abstractcore>=2.25.1` in the base install and the `[apple]`/`[gpu]` extras): the Linux command sandbox reaches an allowed folder inside a refused one, and `browser_probe` accepts the run's `_sandbox` stamp.