AbstractRuntime 0.9.0__tar.gz → 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (704) hide show
  1. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/CHANGELOG.md +38 -0
  2. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/PKG-INFO +5 -5
  3. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/README.md +1 -1
  4. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/README.md +1 -1
  5. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/api.md +1 -1
  6. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/architecture.md +2 -1
  7. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/automations.md +33 -4
  8. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/faq.md +1 -1
  9. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/integrations/abstractcore.md +9 -2
  10. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/llms-full.txt +48 -11
  11. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/llms.txt +2 -2
  12. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/pyproject.toml +8 -4
  13. abstractruntime-0.10.0/release-notes.md +20 -0
  14. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/__init__.py +4 -0
  15. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/config_facade.py +25 -0
  16. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/run_facade.py +117 -114
  17. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +7 -0
  18. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/triggers/__init__.py +4 -1
  19. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/triggers/registry.py +18 -2
  20. abstractruntime-0.10.0/src/abstractruntime/triggers/schedule.py +553 -0
  21. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +79 -0
  22. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/compiler.py +18 -2
  23. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/builtins.py +15 -1
  24. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/executor.py +124 -4
  25. abstractruntime-0.10.0/src/abstractruntime/visualflow_compiler/visual/loop_back_check.py +104 -0
  26. abstractruntime-0.10.0/src/abstractruntime/visualflow_compiler/visual/loop_limit_lowering.py +154 -0
  27. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/models.py +5 -0
  28. abstractruntime-0.10.0/src/abstractruntime/visualflow_compiler/visual/reroute_lowering.py +127 -0
  29. abstractruntime-0.10.0/tests/fixtures/schedule_v1_corpus.json +6662 -0
  30. abstractruntime-0.10.0/tests/test_automation_calendar_schedule.py +76 -0
  31. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_browser_probe_target_walling.py +15 -0
  32. abstractruntime-0.10.0/tests/test_config_facade_voice_input_hint.py +54 -0
  33. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_packaging_extras.py +3 -3
  34. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_r12_workspace_sandbox.py +36 -2
  35. abstractruntime-0.10.0/tests/test_schedule_v1_corpus.py +46 -0
  36. abstractruntime-0.10.0/tests/test_schedule_v2_calendar.py +286 -0
  37. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_trigger_registry.py +10 -6
  38. abstractruntime-0.10.0/tests/test_visual_loop_back_out_of_body.py +117 -0
  39. abstractruntime-0.10.0/tests/test_visual_loop_limit_and_list_nodes.py +254 -0
  40. abstractruntime-0.10.0/tests/test_visual_loop_limit_on_wire.py +177 -0
  41. abstractruntime-0.10.0/tests/test_visual_reroute_lowering.py +125 -0
  42. abstractruntime-0.10.0/tests/test_visual_set_vars_pins.py +70 -0
  43. abstractruntime-0.10.0/tests/test_voice_stream_is_not_a_wait.py +256 -0
  44. abstractruntime-0.9.0/release-notes.md +0 -23
  45. abstractruntime-0.9.0/src/abstractruntime/triggers/schedule.py +0 -249
  46. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/.github/workflows/ci.yml +0 -0
  47. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/.github/workflows/release.yml +0 -0
  48. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/.gitignore +0 -0
  49. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/ACKNOWLEDGMENTS.md +0 -0
  50. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/CODE_OF_CONDUCT.md +0 -0
  51. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/CONTRIBUTING.md +0 -0
  52. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/LICENSE +0 -0
  53. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/ROADMAP.md +0 -0
  54. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/SECURITY.md +0 -0
  55. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
  56. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
  57. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
  58. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
  59. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
  60. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
  61. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
  62. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/adr/README.md +0 -0
  63. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/artifacts.md +0 -0
  64. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/README.md +0 -0
  65. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/001_runtime_kernel.md +0 -0
  66. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
  67. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
  68. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
  69. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
  70. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
  71. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
  72. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
  73. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/003_wait_primitives.md +0 -0
  74. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
  75. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
  76. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
  77. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
  78. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/004_scheduler_driver.md +0 -0
  79. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
  80. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
  81. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
  82. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/009_artifact_store.md +0 -0
  83. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/010_examples_and_composition.md +0 -0
  84. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/011_subworkflow_support.md +0 -0
  85. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
  86. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
  87. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
  88. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
  89. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
  90. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
  91. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
  92. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
  93. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
  94. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
  95. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
  96. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
  97. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
  98. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
  99. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
  100. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
  101. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
  102. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
  103. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
  104. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
  105. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
  106. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
  107. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
  108. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/004_tests.md +0 -0
  109. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/005_docs_updates.md +0 -0
  110. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
  111. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
  112. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
  113. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/README.md +0 -0
  114. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
  115. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
  116. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
  117. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
  118. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
  119. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
  120. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
  121. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
  122. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
  123. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
  124. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
  125. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
  126. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
  127. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
  128. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
  129. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_portability/README.md +0 -0
  130. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
  131. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
  132. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
  133. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
  134. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
  135. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
  136. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
  137. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
  138. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
  139. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
  140. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
  141. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
  142. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
  143. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
  144. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
  145. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
  146. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
  147. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
  148. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
  149. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
  150. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
  151. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
  152. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
  153. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
  154. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
  155. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
  156. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
  157. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
  158. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
  159. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/email.md +0 -0
  160. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/entity-runtime.md +0 -0
  161. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/evidence.md +0 -0
  162. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/getting-started.md +0 -0
  163. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/limits.md +0 -0
  164. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/manual_testing.md +0 -0
  165. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/mcp-worker.md +0 -0
  166. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/proposal.md +0 -0
  167. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/provenance.md +0 -0
  168. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/snapshots.md +0 -0
  169. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/tool-approval.md +0 -0
  170. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/tools-comms.md +0 -0
  171. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/troubleshooting.md +0 -0
  172. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/docs/workflow-bundles.md +0 -0
  173. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/01_hello_world.py +0 -0
  174. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/02_ask_user.py +0 -0
  175. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/03_wait_until.py +0 -0
  176. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/04_multi_step.py +0 -0
  177. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/05_persistence.py +0 -0
  178. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/06_llm_integration.py +0 -0
  179. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/07_react_agent.py +0 -0
  180. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/examples/README.md +0 -0
  181. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/mkdocs.yml +0 -0
  182. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/pytest.ini +0 -0
  183. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/scripts/backfill_diary_edges.py +0 -0
  184. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/scripts/generate_llms_full.py +0 -0
  185. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/__init__.py +0 -0
  186. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automation_queries.py +0 -0
  187. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/__init__.py +0 -0
  188. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/adapters.py +0 -0
  189. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/attention.py +0 -0
  190. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/bundle.py +0 -0
  191. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
  192. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
  193. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/commands.py +0 -0
  194. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/controller.py +0 -0
  195. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/ledger.py +0 -0
  196. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/models.py +0 -0
  197. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/automations/service.py +0 -0
  198. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/__init__.py +0 -0
  199. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/config.py +0 -0
  200. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/effect_cancellation.py +0 -0
  201. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/event_keys.py +0 -0
  202. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/health.py +0 -0
  203. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/live_deltas.py +0 -0
  204. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/models.py +0 -0
  205. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/policy.py +0 -0
  206. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/progress_channel.py +0 -0
  207. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/run_attribution.py +0 -0
  208. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/run_identity.py +0 -0
  209. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/run_lifecycle.py +0 -0
  210. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/runtime.py +0 -0
  211. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/spec.py +0 -0
  212. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/tool_scope.py +0 -0
  213. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/core/vars.py +0 -0
  214. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/documents/__init__.py +0 -0
  215. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/documents/charts.py +0 -0
  216. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/documents/docx.py +0 -0
  217. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/documents/pdf.py +0 -0
  218. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/__init__.py +0 -0
  219. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/actions.py +0 -0
  220. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/automations.py +0 -0
  221. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/binding.py +0 -0
  222. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/feeder.py +0 -0
  223. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/frame.py +0 -0
  224. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/email/inbox.py +0 -0
  225. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/evidence/__init__.py +0 -0
  226. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/evidence/recorder.py +0 -0
  227. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/history_bundle.py +0 -0
  228. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/__init__.py +0 -0
  229. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/act_only.py +0 -0
  230. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/chat.py +0 -0
  231. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/communities.py +0 -0
  232. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/diary.py +0 -0
  233. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/digest.py +0 -0
  234. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/entity_runtime.py +0 -0
  235. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/fingerprint.py +0 -0
  236. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/lease.py +0 -0
  237. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/life.py +0 -0
  238. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/memory_reader.py +0 -0
  239. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/night_voice.py +0 -0
  240. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/phase_graph.py +0 -0
  241. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/phase_spec.py +0 -0
  242. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/prelude.py +0 -0
  243. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/prompt_overlay.py +0 -0
  244. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/reflection.py +0 -0
  245. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
  246. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/substrate.py +0 -0
  247. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/tool_effects.py +0 -0
  248. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/tool_policy.py +0 -0
  249. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/tools.py +0 -0
  250. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/identity/visit_workflow.py +0 -0
  251. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/__init__.py +0 -0
  252. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
  253. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/command_sandbox_host.py +0 -0
  254. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
  255. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
  256. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
  257. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
  258. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
  259. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
  260. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +0 -0
  261. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
  262. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
  263. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
  264. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
  265. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
  266. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
  267. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
  268. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/mcp_facade.py +0 -0
  269. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
  270. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
  271. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
  272. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
  273. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/server_facade.py +0 -0
  274. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
  275. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/structured_facade.py +0 -0
  276. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
  277. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
  278. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
  279. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
  280. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
  281. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
  282. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
  283. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
  284. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
  285. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
  286. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/__init__.py +0 -0
  287. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/active_context.py +0 -0
  288. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/active_memory.py +0 -0
  289. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/compaction.py +0 -0
  290. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/kg_packets.py +0 -0
  291. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/memact_composer.py +0 -0
  292. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/recall_levels.py +0 -0
  293. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/memory/token_budget.py +0 -0
  294. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/rendering/__init__.py +0 -0
  295. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
  296. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/rendering/json_stringify.py +0 -0
  297. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/scheduler/__init__.py +0 -0
  298. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/scheduler/convenience.py +0 -0
  299. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/scheduler/multi_store.py +0 -0
  300. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/scheduler/registry.py +0 -0
  301. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/scheduler/scheduler.py +0 -0
  302. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/session_history.py +0 -0
  303. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/session_turns.py +0 -0
  304. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/__init__.py +0 -0
  305. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/artifacts.py +0 -0
  306. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/base.py +0 -0
  307. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/commands.py +0 -0
  308. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/in_memory.py +0 -0
  309. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/json_files.py +0 -0
  310. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/lease.py +0 -0
  311. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/ledger_chain.py +0 -0
  312. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/ledger_slim.py +0 -0
  313. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/observable.py +0 -0
  314. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/offloading.py +0 -0
  315. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/serialize.py +0 -0
  316. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/snapshots.py +0 -0
  317. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/sqlite.py +0 -0
  318. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/storage/steer_sidecar.py +0 -0
  319. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/triggers/email_received.py +0 -0
  320. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/triggers/manual.py +0 -0
  321. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/triggers/protocol.py +0 -0
  322. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/turn_grounding.py +0 -0
  323. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/utils/__init__.py +0 -0
  324. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/utils/atomic_files.py +0 -0
  325. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/utils/file_filters.py +0 -0
  326. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/utils/workspace_paths.py +0 -0
  327. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
  328. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
  329. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
  330. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
  331. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
  332. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
  333. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
  334. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
  335. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
  336. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
  337. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
  338. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
  339. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
  340. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
  341. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
  342. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
  343. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
  344. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
  345. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
  346. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/workflow_bundle/models.py +0 -0
  347. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/workflow_bundle/packer.py +0 -0
  348. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/workflow_bundle/reader.py +0 -0
  349. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/src/abstractruntime/workflow_bundle/registry.py +0 -0
  350. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/README.md +0 -0
  351. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/automation_harness.py +0 -0
  352. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/conftest.py +0 -0
  353. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/email_wp2_support.py +0 -0
  354. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/live_email/conftest.py +0 -0
  355. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/live_email/live_email_support.py +0 -0
  356. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/live_email/test_email_live_runtime.py +0 -0
  357. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_comms_facade.py +0 -0
  358. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_discovery_facade.py +0 -0
  359. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_host_facade.py +0 -0
  360. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_run_facade.py +0 -0
  361. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_server_facade.py +0 -0
  362. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_structured_facade.py +0 -0
  363. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_abstractcore_telegram_facade.py +0 -0
  364. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_active_context_policy.py +0 -0
  365. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_active_memory.py +0 -0
  366. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_agora_agent_alias_identity.py +0 -0
  367. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_agora_tools_http.py +0 -0
  368. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_analyze_media_addressing_and_walling.py +0 -0
  369. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_answer_user_effect.py +0 -0
  370. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_artifacts.py +0 -0
  371. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_commands.py +0 -0
  372. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_controller.py +0 -0
  373. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_controller_recovery.py +0 -0
  374. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_definition.py +0 -0
  375. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_discussion_isolation.py +0 -0
  376. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_email_results.py +0 -0
  377. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_growing_context.py +0 -0
  378. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_index.py +0 -0
  379. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_next_fire.py +0 -0
  380. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_occurrence_input_resolver.py +0 -0
  381. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_occurrence_recovery.py +0 -0
  382. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_replay_read_only.py +0 -0
  383. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_retry.py +0 -0
  384. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_session_turns.py +0 -0
  385. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_status.py +0 -0
  386. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_automation_tool_approval.py +0 -0
  387. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_budget_law_no_unrequested_caps.py +0 -0
  388. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_capability_default_reasoning.py +0 -0
  389. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_chat_summarizer_integration.py +0 -0
  390. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_code_node_restricted_python.py +0 -0
  391. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_command_sandbox_host_facade.py +0 -0
  392. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_command_store.py +0 -0
  393. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_compaction_helpers.py +0 -0
  394. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_compaction_summarizer_route.py +0 -0
  395. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_config_facade_models_engines.py +0 -0
  396. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_control_adapter_while.py +0 -0
  397. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_controller_bundle_packaged.py +0 -0
  398. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_crash_ordering_inversions.py +0 -0
  399. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_create_if_absent.py +0 -0
  400. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_data_registry_facade.py +0 -0
  401. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_camera_gating.py +0 -0
  402. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_comms_gating.py +0 -0
  403. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_include_skim_files.py +0 -0
  404. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_include_skim_folders.py +0 -0
  405. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_include_skim_web.py +0 -0
  406. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_default_tools_search_files_executor.py +0 -0
  407. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_diary_capture.py +0 -0
  408. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_diary_write_rescue.py +0 -0
  409. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_directory_lease.py +0 -0
  410. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_disabled_toolsets_seam.py +0 -0
  411. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_discovery_survives_unbuildable_default.py +0 -0
  412. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_discovery_tts_unavailable_reason.py +0 -0
  413. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_discovery_voice_openai_api_key.py +0 -0
  414. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_discussion_session_anchor.py +0 -0
  415. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_document_markdown_tables.py +0 -0
  416. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_document_renderers_hr_quote.py +0 -0
  417. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_durable_toolsets.py +0 -0
  418. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_durable_write_discipline.py +0 -0
  419. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
  420. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_effect_cancellation.py +0 -0
  421. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_effect_issuance_idempotency.py +0 -0
  422. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_effect_payload_stays_json_serializable.py +0 -0
  423. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_election_consequence_teaching.py +0 -0
  424. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_binding_and_refiner.py +0 -0
  425. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_gate_fixes.py +0 -0
  426. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_inbox_and_trigger.py +0 -0
  427. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_regate_fixes.py +0 -0
  428. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_review_fixes.py +0 -0
  429. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_self_trigger_loop.py +0 -0
  430. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_email_toolset_and_walls.py +0 -0
  431. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_emergence_experiment.py +0 -0
  432. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_emit_event_uses_wait_index.py +0 -0
  433. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_emit_event_without_workflow_registry.py +0 -0
  434. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_endpoint_profile_route_context.py +0 -0
  435. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_awake_memory_fixes.py +0 -0
  436. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_brain_effects.py +0 -0
  437. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_chat_driver.py +0 -0
  438. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_chat_tools_reflection.py +0 -0
  439. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_diary.py +0 -0
  440. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_execute_tool.py +0 -0
  441. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_fetch_url_tool.py +0 -0
  442. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_history_window.py +0 -0
  443. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_life_loop.py +0 -0
  444. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_memory_richness.py +0 -0
  445. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_phase_graph_conformance.py +0 -0
  446. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_react_visit_window.py +0 -0
  447. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_recent_memories.py +0 -0
  448. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_runtime.py +0 -0
  449. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_search_memory.py +0 -0
  450. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
  451. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_substrate_resolution.py +0 -0
  452. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_visit_honesty.py +0 -0
  453. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_workspace_cap.py +0 -0
  454. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_entity_workspace_tools.py +0 -0
  455. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_event_wait_index.py +0 -0
  456. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
  457. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_evidence_recorder.py +0 -0
  458. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
  459. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_execute_command_output_offload.py +0 -0
  460. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_execution_capability_discovery.py +0 -0
  461. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_explicit_eject_other_clients.py +0 -0
  462. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_factory_default_retry_policy.py +0 -0
  463. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
  464. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_format_repair_nudge.py +0 -0
  465. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_fresh_install_no_provider.py +0 -0
  466. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_gateway_facades_c4899.py +0 -0
  467. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_git_read_only_refiner.py +0 -0
  468. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_hf_process_residency_merge.py +0 -0
  469. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_history_window_multimodal.py +0 -0
  470. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_hot_path_store_reads.py +0 -0
  471. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_indexed_idempotency_lookup.py +0 -0
  472. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_integration_abstractcore.py +0 -0
  473. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_integrations_abstractcore.py +0 -0
  474. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_json_file_run_store_children_index.py +0 -0
  475. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_json_run_cache_bound.py +0 -0
  476. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_json_store_scan_memo.py +0 -0
  477. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_jsonl_ledger_recovery.py +0 -0
  478. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_kg_learn_and_recall_contract.py +0 -0
  479. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_ledger_chain.py +0 -0
  480. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_ledger_record_slimming.py +0 -0
  481. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_ledger_subscription.py +0 -0
  482. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_live_token_deltas.py +0 -0
  483. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_media_artifact_refs.py +0 -0
  484. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
  485. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
  486. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_payload_shape_refusal.py +0 -0
  487. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_requires_prompt.py +0 -0
  488. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_response_schema_normalization.py +0 -0
  489. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_structured_output_fallback.py +0 -0
  490. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_text_phase_progress.py +0 -0
  491. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_truncation_retry_contract.py +0 -0
  492. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_use_context_appends_turn.py +0 -0
  493. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
  494. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_client_grounding_tail.py +0 -0
  495. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_client_media_artifacts.py +0 -0
  496. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_client_system_context.py +0 -0
  497. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_client_tool_call_parsing.py +0 -0
  498. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_retry_classification.py +0 -0
  499. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_llm_streaming_on_token.py +0 -0
  500. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_local_helper_tool_exposure.py +0 -0
  501. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_local_residency_host_sweep.py +0 -0
  502. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
  503. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_max_iterations_ceiling.py +0 -0
  504. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mcp_remote_tool_executor.py +0 -0
  505. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mcp_runs_untrusted_and_facade.py +0 -0
  506. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mcp_worker_logging.py +0 -0
  507. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mcp_worker_security.py +0 -0
  508. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mcp_worker_stdio.py +0 -0
  509. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_media_artifact_resolution.py +0 -0
  510. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_media_capability_default_routing.py +0 -0
  511. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_media_only_requests_skip_text_client.py +0 -0
  512. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_media_subprocess.py +0 -0
  513. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memact_composer_from_kg_result.py +0 -0
  514. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_appraise_handler.py +0 -0
  515. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_communities.py +0 -0
  516. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
  517. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_packets.py +0 -0
  518. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_predicate_aliasing.py +0 -0
  519. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_query_packetization_restart.py +0 -0
  520. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
  521. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
  522. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_note_effect.py +0 -0
  523. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_query_effect.py +0 -0
  524. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_query_rich_filters.py +0 -0
  525. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
  526. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_seam_handlers.py +0 -0
  527. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_seam_sqlite_durability.py +0 -0
  528. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_memory_tag_effect.py +0 -0
  529. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mlx_generation_serialization.py +0 -0
  530. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_mlx_process_residency_merge.py +0 -0
  531. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_model_eject_cancel.py +0 -0
  532. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_model_residency_clean_switch.py +0 -0
  533. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_model_residency_control_plane.py +0 -0
  534. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
  535. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_multi_store_scheduler.py +0 -0
  536. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_multimodal_abstractcore_integration.py +0 -0
  537. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_native_mlx_application_wiring.py +0 -0
  538. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_native_mlx_execution_controls_live.py +0 -0
  539. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_native_tool_channel.py +0 -0
  540. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_night_voice.py +0 -0
  541. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_no_default_provider_refusal_ux.py +0 -0
  542. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_offload_answer_chain_c4978.py +0 -0
  543. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
  544. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_offloading.py +0 -0
  545. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_parallel_readonly_tool_execution.py +0 -0
  546. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_pause_resume.py +0 -0
  547. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_pdf_unicode_rendering.py +0 -0
  548. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_personal_cycle.py +0 -0
  549. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_phantom_attachment_index.py +0 -0
  550. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_phase_graph_artifact_control.py +0 -0
  551. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_phase_graph_obedience.py +0 -0
  552. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_phase_vocabulary_migration.py +0 -0
  553. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
  554. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_cache_export_import.py +0 -0
  555. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
  556. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_cache_modules.py +0 -0
  557. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_cache_posture_inheritance.py +0 -0
  558. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
  559. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_prompt_overlay.py +0 -0
  560. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_provider_endpoint_profile_resolution.py +0 -0
  561. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_provider_pin_routing_isolation.py +0 -0
  562. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_queryable_run_store.py +0 -0
  563. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
  564. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_read_idle_threading.py +0 -0
  565. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_readoption_experiment.py +0 -0
  566. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_real_integration.py +0 -0
  567. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_realize_election.py +0 -0
  568. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_recall_levels_policy.py +0 -0
  569. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_remote_client_cancel.py +0 -0
  570. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_remote_llm_client.py +0 -0
  571. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_remote_speculation_defaults.py +0 -0
  572. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_rendering_agent_trace_report.py +0 -0
  573. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_rendering_json_stringify.py +0 -0
  574. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_report_branding.py +0 -0
  575. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_resident_media_generation.py +0 -0
  576. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_resume_concurrent_same_wait.py +0 -0
  577. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_retry_idempotency.py +0 -0
  578. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_run_history_bundle.py +0 -0
  579. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_run_index_workspace_root.py +0 -0
  580. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_run_mutation_lock.py +0 -0
  581. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_run_scoped_tool_policy.py +0 -0
  582. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_run_tool_scope_ceiling.py +0 -0
  583. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_browser_session_boundary.py +0 -0
  584. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
  585. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_default_provider_model_refresh.py +0 -0
  586. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_effect_invocation_trace.py +0 -0
  587. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_health_and_bounded_vars.py +0 -0
  588. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_install_boundary.py +0 -0
  589. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
  590. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_node_traces.py +0 -0
  591. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_start_seeds_tool_support.py +0 -0
  592. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_runtime_tick_step_gate.py +0 -0
  593. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_scheduler.py +0 -0
  594. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_send_email_refiner.py +0 -0
  595. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_send_email_self_default_policy.py +0 -0
  596. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
  597. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_history.py +0 -0
  598. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_prompt_cache_attribution.py +0 -0
  599. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_prompt_cache_visibility.py +0 -0
  600. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_route_stamp.py +0 -0
  601. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_session_start_cost.py +0 -0
  602. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_shell_tool_exposure.py +0 -0
  603. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_snapshots.py +0 -0
  604. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_speculation_inheritance.py +0 -0
  605. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_speculation_reaches_provider_construction.py +0 -0
  606. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_sqlite_ledger_store.py +0 -0
  607. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_start_subworkflow_async_wait.py +0 -0
  608. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
  609. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
  610. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_steer_sidecar.py +0 -0
  611. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_storage_deletion.py +0 -0
  612. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_structured_output_schema_enum.py +0 -0
  613. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_subworkflow.py +0 -0
  614. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_terminal_effect_completion.py +0 -0
  615. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
  616. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_thinking_inheritance.py +0 -0
  617. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
  618. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_approval_executor.py +0 -0
  619. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_approval_resume_executes.py +0 -0
  620. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_approval_wait_key_identity.py +0 -0
  621. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_calls_idempotency_keys.py +0 -0
  622. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_catalog.py +0 -0
  623. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_descriptor_registry.py +0 -0
  624. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_argument_sanitization.py +0 -0
  625. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_error_output_detection.py +0 -0
  626. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_filename_alias.py +0 -0
  627. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
  628. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_read_file_aliases.py +0 -0
  629. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_executor_timeout.py +0 -0
  630. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_inventory_facade.py +0 -0
  631. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_invoke_effect.py +0 -0
  632. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_policy_and_mounts.py +0 -0
  633. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_tool_wait_allowlist_safety.py +0 -0
  634. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_topic_election_world_model.py +0 -0
  635. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_trace_context_propagation.py +0 -0
  636. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_trigger_schedule_math.py +0 -0
  637. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_turn_grounding_byte_stability.py +0 -0
  638. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_turn_grounding_carriers_a3.py +0 -0
  639. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_vars_query_effect.py +0 -0
  640. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visit_ab_fixture.py +0 -0
  641. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visit_midturn_elections.py +0 -0
  642. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visit_midturn_resume.py +0 -0
  643. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visit_workflow.py +0 -0
  644. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
  645. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
  646. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
  647. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
  648. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
  649. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
  650. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_entity_memory_nodes.py +0 -0
  651. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
  652. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_llm_call_partial_override.py +0 -0
  653. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
  654. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_memact_compose_node.py +0 -0
  655. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
  656. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
  657. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
  658. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_unknown_node_type_refuses.py +0 -0
  659. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
  660. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_add_message_builtin.py +0 -0
  661. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
  662. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_agora_react_agent.py +0 -0
  663. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_call_tool_node.py +0 -0
  664. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
  665. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_compiler_basic.py +0 -0
  666. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
  667. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_continue_on_error.py +0 -0
  668. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_edit_json_schema_node.py +0 -0
  669. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
  670. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_file_nodes_workspace.py +0 -0
  671. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_function_library.py +0 -0
  672. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_get_element_node.py +0 -0
  673. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_get_random_element_node.py +0 -0
  674. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_get_var_node.py +0 -0
  675. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_has_tools_builtin.py +0 -0
  676. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
  677. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
  678. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_make_object_node.py +0 -0
  679. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_media_nodes.py +0 -0
  680. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_memory_effect_nodes.py +0 -0
  681. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_memory_source_pins.py +0 -0
  682. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_pin_expressions.py +0 -0
  683. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_prompt_only.py +0 -0
  684. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_random_nodes.py +0 -0
  685. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_schema_enum_switch.py +0 -0
  686. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_string_contains_replace.py +0 -0
  687. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_visualflow_tool_parameters_node.py +0 -0
  688. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_voice_openai_api_key_path.py +0 -0
  689. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_w4_feelings_lens.py +0 -0
  690. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_wait_event_deadline.py +0 -0
  691. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_wait_event_prompt_metadata.py +0 -0
  692. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_wait_until_streak.py +0 -0
  693. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_wait_until_utc_normalization.py +0 -0
  694. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workflow_bundle_registry.py +0 -0
  695. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_builtin_deny.py +0 -0
  696. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_context_allowed_workspaces.py +0 -0
  697. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
  698. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_policy_allowlist_mode.py +0 -0
  699. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
  700. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
  701. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_prompt_context.py +0 -0
  702. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_read_only.py +0 -0
  703. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_workspace_writable_paths.py +0 -0
  704. {abstractruntime-0.9.0 → abstractruntime-0.10.0}/tests/test_write_chart.py +0 -0
@@ -5,6 +5,44 @@ 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
+ ## [0.10.0] - 2026-10-15
9
+
10
+ ### Added
11
+
12
+ - Trigger source `schedule@2`: `{kind: "daily", at: "HH:MM"}`, `{kind: "weekly", days: [...], at}` and `{kind: "monthly", day: 1..31 | "last", at}` evaluated on wall time in the config's `time_zone` (IANA, converted with `zoneinfo`: a skipped wall time runs at the shifted instant, a repeated one runs once; a day beyond the month's length runs on its last day), plus `{kind: "every"}` and `{kind: "once"}` with `schedule@1`'s meaning (a `once` may give a wall time `at` in `time_zone`). Same coalescing and pause policy as `schedule@1`; event ids `schedule@2:<binding_id>:<tick>`. `validate_time_zone(name)` and `time_zone_names()` are exported from `abstractruntime.triggers`. See `docs/automations.md`.
13
+ - `integrations.abstractcore.config_facade.voice_input_hint(route, host=None)`: AbstractCore's served one-line hint for a configured speech-input route (`abstractcore.config.recommendations.voice_input_hint`, AbstractCore >= 2.26.0), so a host such as AbstractGateway serves it without importing AbstractCore itself. The AbstractCore floor is 2.26.0.
14
+ - A limit on an execution wire: `edge.data.loopLimit = {"max": N}` (the editor's ↺N badge on a wire that makes execution repeat). Before compile, `visual/loop_limit_lowering.py` turns it into a `loop_limit` node on that wire (`again` to the wire's target; `limit_reached` to the other branch when the wire leaves an If/Else and that branch is not itself a limited wire, else nothing: the path ends at the limit), re-keying the target's per-path values and entry list. A run tree shows the lowered node as "Loop limit N". `VisualEdge` now carries `data` (older runtimes never read it, so a limited flow runs unlimited there).
15
+ - VisualFlow `get_vars` node (Get Variables): a data node with one output per variable, its pin id the variable name (dotted paths allowed); each output reads the run variable's current value, or null when it is not set.
16
+ - VisualFlow `loop_limit` node (Loop Limit): exec outputs `again` (taken while fewer than `max` passes were let through) and `limit_reached` (then the count starts again from 0), data output `count` (the pass number). The count lives in `run.vars._temp.loop_limits.<node id>`, so it survives pause/resume. It belongs to the current iteration of the enclosing ForEach / For / While (each item, and each new entry of that loop, starts from 0); with no enclosing loop, to the run. Its `max` comes only from its own pin, never from the previous step's output.
17
+ - VisualFlow `add_to_list` node (Add to List Variable): `name`, `item` (added as one element), `items` (each element added); a missing or null variable starts as `[]`; a variable that holds something else, or `items` that is not a list, fails the step naming it; reads and writes in one step; output `list`.
18
+ - String Template: a placeholder reads an input pin of its name, then the `vars` object, then the run variable (top-level names not starting with `_`). A list or object with no filter is written as JSON (it was Python's `str()`).
19
+
20
+ ### Changed
21
+
22
+ - An execution wire that loops back out of a ForEach / For / While body (from inside the body to the loop node itself or to anything before it) is refused when the flow compiles: "Wire <source>.<pin> -> <target> goes back out of <loop>'s loop body: the run would never end. A path inside a loop body can only repeat within the body; to repeat the whole loop, wire the loop-back after the loop's done." Such a wire re-entered the loop with its frame still on the control stack, so the stack grew by one frame per pass and the run never ended (a Loop Limit on it never reached its max). A loop-back that goes through the loop's `done`, or that stays inside the body, is unchanged (`visual/loop_back_check.py`).
23
+ - `schedule@1` is unchanged: its configs normalize byte for byte as before and existing automations keep their tick grid (`tests/test_schedule_v1_corpus.py` freezes the 0.9.1 answers on real automation configs).
24
+
25
+ ### Fixed
26
+
27
+ - Set Variables (and Add to List Variable) only take what their own pins carry (a wire, a value set on the node, an expression). Before, keys of the previous step's output were written as variables too.
28
+ - Set Variables (`set_vars`): every data input pin besides `updates` is one variable, written under the pin's id (dotted paths nest) with its value: a wire, else the pin's default. These win over the same name in the `updates` object. AbstractFlow edits them as rows (name, type, value), so one node initialises several variables, wired or literal. A flow using such rows needs this runtime: an older one writes only `updates`. Test: `tests/test_visual_set_vars_pins.py`.
29
+ - VisualFlow reroute ("relay") nodes: a dot in AbstractFlow that lets one output feed several inputs along a tidy path. They are visual only: before compiling, every chain `source -> reroute (-> reroute ...) -> target` is rewired `source -> target` and the reroutes are removed (`visualflow_compiler/visual/reroute_lowering.py`, run before the multi-entry lowering). A reroute with no source feeds nothing (its targets keep their defaults); per-path values that name a reroute point at its real source. Data wires only: an execution wire through a reroute, a second input into one, or a cycle of reroutes is refused with a message naming the wire. A flow with a connected reroute needs this runtime (older ones refuse the unknown node type). Test: `tests/test_visual_reroute_lowering.py`.
30
+
31
+ ## [0.9.1] - 2026-10-08
32
+
33
+ ### Security
34
+
35
+ - `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`.
36
+
37
+ ### Fixed
38
+
39
+ - `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.
40
+ - `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.
41
+
42
+ ### Changed
43
+
44
+ - 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.
45
+
8
46
  ## [0.9.0] - 2026-10-05
9
47
 
10
48
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: AbstractRuntime
3
- Version: 0.9.0
3
+ Version: 0.10.0
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.25.0
23
+ Requires-Dist: abstractcore>=2.26.0
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.25.0; extra == 'apple'
38
+ Requires-Dist: abstractcore[apple]>=2.26.0; 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.25.0; extra == 'gpu'
45
+ Requires-Dist: abstractcore[gpu]>=2.26.0; 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'
@@ -159,7 +159,7 @@ Kernel (import-light):
159
159
  - Stop that reaches the running effect: `Runtime.cancel_run(...)` signals the in-flight model or tool call, which ends as a `cancelled` ledger record (never retried); a model unload stops the calls using that model first (`docs/api.md`)
160
160
  - host pause at step boundaries: `Runtime.tick(..., step_gate=...)`
161
161
  - run-tree tool ceiling: an explicit `allowed_tools` list can only narrow across child runs, and approval policy never widens it
162
- - automations: run a workflow on a schedule (`schedule@1`, fixed UTC intervals), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
162
+ - automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
163
163
  - explicit run ids: `Runtime.start(..., run_id=...)` creates a run only if the id is free (`RunStore.create_if_absent`), and `run_mutation_lock(run_id)` serializes a run's writers in a process
164
164
 
165
165
  Durability + storage:
@@ -108,7 +108,7 @@ Kernel (import-light):
108
108
  - Stop that reaches the running effect: `Runtime.cancel_run(...)` signals the in-flight model or tool call, which ends as a `cancelled` ledger record (never retried); a model unload stops the calls using that model first (`docs/api.md`)
109
109
  - host pause at step boundaries: `Runtime.tick(..., step_gate=...)`
110
110
  - run-tree tool ceiling: an explicit `allowed_tools` list can only narrow across child runs, and approval policy never widens it
111
- - automations: run a workflow on a schedule (`schedule@1`, fixed UTC intervals), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
111
+ - automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
112
112
  - explicit run ids: `Runtime.start(..., run_id=...)` creates a run only if the id is free (`RunStore.create_if_absent`), and `run_mutation_lock(run_id)` serializes a run's writers in a process
113
113
 
114
114
  Durability + storage:
@@ -36,7 +36,7 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
36
36
 
37
37
  ## Features (reference)
38
38
 
39
- - `automations.md` — automations: a workflow run on a schedule or on request as a durable controller run; triggers (`schedule@1`, `manual@1`, `email.received@1`, entry-point sources), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
39
+ - `automations.md` — automations: a workflow run on a schedule or on request as a durable controller run; triggers (`schedule@1`, `schedule@2` calendar rules in a time zone, `manual@1`, `email.received@1`, entry-point sources), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
40
40
  - `entity-runtime.md` — per-entity runtimes for summoned entities: homes, the one-writer lease, act-only diary privacy (`$act_only` refs), durable visit waits with deadlines
41
41
  - `evidence.md` — artifact-backed evidence capture for external-boundary tools
42
42
  - `mcp-worker.md` — MCP worker CLI (`abstractruntime-mcp-worker`)
@@ -241,7 +241,7 @@ from abstractruntime.triggers import get_trigger_adapter, trigger_sources
241
241
  - reads: `get_automation(run_store, id)`, `list_occurrences(runtime, id, cursor=, limit=)`, `list_attention(ledger_store, id, after_seq=, cursor=, limit=)`, `pending_waits(run_store, id, limit=)` with typed waits (`ask_user`, `tool_approval`, `event`) and `ANSWER_PAYLOADS`; `list_automations(run_store, status=, cursor=, limit=)`, `automation_summary(run)`, `latest_occurrence(run_store, id)`
242
242
  - `start_discussion(runtime, *, automation_id, occurrence_index, request_id, prompt, workspace_root, actor_id=None)`: a separate conversation forked at any occurrence N, seeded with the automation's whole timeline 1..N, working in its own writable `workspace_root` with the automation's workspace mounted read-only
243
243
  - controller bundle: `register_controller_bundle(registry)`, `controller_workflow_spec()`, `controller_bundle_path()`; `CONTROLLER_WORKFLOW_ID` is `abstractframework.automation-controller@1.0.0:controller`
244
- - trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `manual@1` and `email.received@1`, third-party sources through the `abstractruntime.trigger_sources` entry-point group
244
+ - trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `schedule@2` (daily/weekly/monthly rules in an IANA time zone; `validate_time_zone`, `time_zone_names`), `manual@1` and `email.received@1`, third-party sources through the `abstractruntime.trigger_sources` entry-point group
245
245
  - definition v2: `policy.email_allowed_recipients` (default `["self"]`), `policy.untrusted_input_tools` (default `[]`) and `notify.channels` (default `["console"]`); attention items carry `channels`
246
246
 
247
247
  ## Email
@@ -332,7 +332,7 @@ flowchart LR
332
332
  subgraph Automations["automations/ + triggers/"]
333
333
  Commands["apply_automation_command"]
334
334
  Controller["controller run<br/>(automation-controller@1.0.0)"]
335
- Triggers["trigger registry<br/>schedule@1, manual@1, email.received@1,<br/>entry-point sources"]
335
+ Triggers["trigger registry<br/>schedule@1, schedule@2, manual@1,<br/>email.received@1, entry-point sources"]
336
336
  Inbox["event inbox<br/>(email/, filled by the host's watcher)"]
337
337
  Queries["get_automation / list_occurrences /<br/>list_attention / pending_waits /<br/>list_automations"]
338
338
  end
@@ -403,6 +403,7 @@ Invariants the design rests on:
403
403
 
404
404
  AbstractRuntime includes a compiler and a portable bundle format:
405
405
  - VisualFlow compiler: `src/abstractruntime/visualflow_compiler/*` (VisualFlow JSON -> `WorkflowSpec`)
406
+ - Reroute (relay) nodes are lowered first and disappear: each chain `source -> reroute (-> reroute) -> target` becomes `source -> target` (`visualflow_compiler/visual/reroute_lowering.py`), so the editor's dots are visual only. Data wires only; an execution wire through a reroute, two inputs into one, or a cycle of reroutes is refused when the flow compiles. A flow with a connected reroute needs this runtime: older ones refuse the unknown node type.
406
407
  - Multi-entry VisualFlow authoring routes are lowered into internal `join_exec` and `path_mux` nodes when a target has multiple incoming `exec-in` edges plus per-route input overrides. This keeps authoring JSON clean while making runtime behavior explicit and restart-safe. See `workflow-bundles.md` for the concrete metadata shape.
407
408
  - VisualFlow document nodes include `read_pdf`, `write_pdf`, and `write_docx`.
408
409
  They use workspace-scoped paths, keep document bytes out of checkpoints, and
@@ -33,7 +33,7 @@ sources), `abstractruntime.automation_queries` (listing), `abstractruntime.sessi
33
33
 
34
34
  ```mermaid
35
35
  flowchart LR
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"]
36
+ Trigger["Trigger source<br/>schedule@1 / schedule@2 / manual@1"] -->|"due tick or run now"| Controller["Controller run<br/>(automation id)<br/>vars._meta.automation<br/>vars._runtime.automation"]
37
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"]
@@ -172,6 +172,35 @@ Config: `{start_at?, every?, until?, count?, anchor?}`.
172
172
  - The event id of a scheduled tick is `schedule@1:<binding_id>:<tick>`. A revision that changes the trigger gets a
173
173
  new `binding_id`, so the new schedule never reuses an old event id.
174
174
 
175
+ ### `schedule@2`
176
+
177
+ `schedule@2` adds calendar rules on wall time in a time zone. `schedule@1` stays registered and unchanged: its
178
+ configs normalize byte for byte as before and its automations keep their tick grid. Use `schedule@2` for new
179
+ automations.
180
+
181
+ Config: `{kind, at?, days?, day?, time_zone?, start_at?, every?, until?, count?}`. The normalized config always
182
+ carries `kind`, then the rule fields, `time_zone`, `start_at`, `anchor` (= `start_at`) and the bounds.
183
+
184
+ | `kind` | Rule fields | Meaning |
185
+ | --- | --- | --- |
186
+ | `every` | `every` (`8h`, `7d`, ...) | Exactly `schedule@1`'s fixed UTC interval from `start_at`. `time_zone` is optional and only labels the schedule. |
187
+ | `once` | `start_at`, or `at: "YYYY-MM-DDTHH:MM"` with `time_zone` | One run. A wall time `at` is converted to `start_at` in `time_zone`. |
188
+ | `daily` | `at: "HH:MM"` | Every day at that wall time. |
189
+ | `weekly` | `days` (non-empty subset of `mon`..`sun`), `at` | Those weekdays at that wall time. `days` is normalized to Monday-first order without duplicates. |
190
+ | `monthly` | `day` (1..31 or `"last"`), `at` | That day of each month; a day beyond the month's length runs on the month's last day (day 31 runs on 28 or 29 February). |
191
+
192
+ - Calendar rules (`daily`, `weekly`, `monthly`) require `time_zone`, an IANA name such as `Europe/Paris`
193
+ (`validate_time_zone(name)`; `time_zone_names()` lists the names the host knows). They take no `every`.
194
+ - Wall times convert to UTC with `zoneinfo`. A wall time that does not exist that day (spring forward) runs at the
195
+ shifted instant: a 02:30 rule runs at 03:30 on that day and at 02:30 afterwards. A wall time that happens twice
196
+ (fall back) runs once, at its first occurrence. A daily 08:00 stays at 08:00 local time across both transitions.
197
+ - Tick 0 is the first rule time at or after `start_at` (default: the creation time). `count` and `until` bound the
198
+ ticks as in `schedule@1`.
199
+ - Missed ticks coalesce and a resume after a pause skips the ticks that passed, exactly as in `schedule@1`. The event
200
+ id of a tick is `schedule@2:<binding_id>:<tick>`.
201
+ - Every instant is computed from its tick index in constant time, so an automation that was down for years catches up
202
+ with one occurrence without walking the missed ticks.
203
+
175
204
  ### `manual@1`
176
205
 
177
206
  Config: `{}`. The automation runs only when asked with `automation.run_now`. A manual run of any automation, whatever
@@ -680,9 +709,9 @@ receives its result directly.
680
709
 
681
710
  ## Limits in v1
682
711
 
683
- - Schedules are fixed UTC intervals (`s`, `m`, `h`, `d`, at most `366d`). There are no cron expressions, calendar
684
- months, time zones or daylight-saving rules, and `anchor` must equal `start_at`.
685
- - The shipped trigger sources are `schedule@1`, `manual@1` and `email.received@1`. There is no generic external
712
+ - Schedules are fixed UTC intervals (`schedule@1`, `schedule@2` `every`) or daily, weekly and monthly wall-time rules
713
+ in an IANA time zone (`schedule@2`). There are no cron expressions, and `anchor` must equal `start_at`.
714
+ - The shipped trigger sources are `schedule@1`, `schedule@2`, `manual@1` and `email.received@1`. There is no generic external
686
715
  event source yet.
687
716
  - Occurrences run one at a time (`serial`), missed ticks coalesce, and a failed occurrence never stops the
688
717
  automation (`failure: "continue"`). These policies cannot be changed.
@@ -49,7 +49,7 @@ Docs: `getting-started.md`. Code: `src/abstractruntime/core/runtime.py`, `src/ab
49
49
  ## How do I run a workflow on a schedule or on request?
50
50
 
51
51
  Create an automation. An automation is a durable controller run that starts the target workflow as a child run (an
52
- occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`) or `manual@1` (run now only).
52
+ occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`), `schedule@2` (the same intervals plus daily, weekly and monthly rules at a wall time in an IANA time zone, daylight-saving correct) or `manual@1` (run now only).
53
53
  `create_automation(...)` creates it, `apply_automation_command(...)` pauses, resumes, runs now, edits, stops the
54
54
  current occurrence, archives it or unarchives it (it comes back paused with its history), and the host drives it
55
55
  like any run (`drive_automation` does this in-process). Nothing is deleted: an archived automation keeps its
@@ -506,6 +506,7 @@ Lists accept a JSON array, a JSON array pasted as a string, or newline-separated
506
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
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
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.
509
510
 
510
511
  ## Prompt-cache control plane and durable blocs
511
512
 
@@ -1048,8 +1049,14 @@ Public durable entry points:
1048
1049
  These helpers create child runs under an existing parent run and execute the real
1049
1050
  `LLM_CALL`, `TOOL_CALLS`, or stream finalization through Runtime rather than
1050
1051
  doing external work in host/controller code. `stream_voice(...)` yields TTS
1051
- stream events for progressive playback and completes the child run with the
1052
- 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=...)`.
1053
1060
 
1054
1061
  Example:
1055
1062
 
@@ -157,7 +157,7 @@ Kernel (import-light):
157
157
  - Stop that reaches the running effect: `Runtime.cancel_run(...)` signals the in-flight model or tool call, which ends as a `cancelled` ledger record (never retried); a model unload stops the calls using that model first (`docs/api.md`)
158
158
  - host pause at step boundaries: `Runtime.tick(..., step_gate=...)`
159
159
  - run-tree tool ceiling: an explicit `allowed_tools` list can only narrow across child runs, and approval policy never widens it
160
- - automations: run a workflow on a schedule (`schedule@1`, fixed UTC intervals), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
160
+ - automations: run a workflow on a schedule (`schedule@1` fixed UTC intervals; `schedule@2` adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives (`email.received@1`, `docs/email.md`) or on request (`manual@1`) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (`docs/automations.md`)
161
161
  - explicit run ids: `Runtime.start(..., run_id=...)` creates a run only if the id is free (`RunStore.create_if_absent`), and `run_mutation_lock(run_id)` serializes a run's writers in a process
162
162
 
163
163
  Durability + storage:
@@ -763,7 +763,7 @@ flowchart LR
763
763
  subgraph Automations["automations/ + triggers/"]
764
764
  Commands["apply_automation_command"]
765
765
  Controller["controller run<br/>(automation-controller@1.0.0)"]
766
- Triggers["trigger registry<br/>schedule@1, manual@1, email.received@1,<br/>entry-point sources"]
766
+ Triggers["trigger registry<br/>schedule@1, schedule@2, manual@1,<br/>email.received@1, entry-point sources"]
767
767
  Inbox["event inbox<br/>(email/, filled by the host's watcher)"]
768
768
  Queries["get_automation / list_occurrences /<br/>list_attention / pending_waits /<br/>list_automations"]
769
769
  end
@@ -834,6 +834,7 @@ Invariants the design rests on:
834
834
 
835
835
  AbstractRuntime includes a compiler and a portable bundle format:
836
836
  - VisualFlow compiler: `src/abstractruntime/visualflow_compiler/*` (VisualFlow JSON -> `WorkflowSpec`)
837
+ - Reroute (relay) nodes are lowered first and disappear: each chain `source -> reroute (-> reroute) -> target` becomes `source -> target` (`visualflow_compiler/visual/reroute_lowering.py`), so the editor's dots are visual only. Data wires only; an execution wire through a reroute, two inputs into one, or a cycle of reroutes is refused when the flow compiles. A flow with a connected reroute needs this runtime: older ones refuse the unknown node type.
837
838
  - Multi-entry VisualFlow authoring routes are lowered into internal `join_exec` and `path_mux` nodes when a target has multiple incoming `exec-in` edges plus per-route input overrides. This keeps authoring JSON clean while making runtime behavior explicit and restart-safe. See `workflow-bundles.md` for the concrete metadata shape.
838
839
  - VisualFlow document nodes include `read_pdf`, `write_pdf`, and `write_docx`.
839
840
  They use workspace-scoped paths, keep document bytes out of checkpoints, and
@@ -1106,7 +1107,7 @@ from abstractruntime.triggers import get_trigger_adapter, trigger_sources
1106
1107
  - reads: `get_automation(run_store, id)`, `list_occurrences(runtime, id, cursor=, limit=)`, `list_attention(ledger_store, id, after_seq=, cursor=, limit=)`, `pending_waits(run_store, id, limit=)` with typed waits (`ask_user`, `tool_approval`, `event`) and `ANSWER_PAYLOADS`; `list_automations(run_store, status=, cursor=, limit=)`, `automation_summary(run)`, `latest_occurrence(run_store, id)`
1107
1108
  - `start_discussion(runtime, *, automation_id, occurrence_index, request_id, prompt, workspace_root, actor_id=None)`: a separate conversation forked at any occurrence N, seeded with the automation's whole timeline 1..N, working in its own writable `workspace_root` with the automation's workspace mounted read-only
1108
1109
  - controller bundle: `register_controller_bundle(registry)`, `controller_workflow_spec()`, `controller_bundle_path()`; `CONTROLLER_WORKFLOW_ID` is `abstractframework.automation-controller@1.0.0:controller`
1109
- - trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `manual@1` and `email.received@1`, third-party sources through the `abstractruntime.trigger_sources` entry-point group
1110
+ - trigger sources: `trigger_sources()`, `get_trigger_adapter(id, version)`, built-ins `schedule@1`, `schedule@2` (daily/weekly/monthly rules in an IANA time zone; `validate_time_zone`, `time_zone_names`), `manual@1` and `email.received@1`, third-party sources through the `abstractruntime.trigger_sources` entry-point group
1110
1111
  - definition v2: `policy.email_allowed_recipients` (default `["self"]`), `policy.untrusted_input_tools` (default `[]`) and `notify.channels` (default `["console"]`); attention items carry `channels`
1111
1112
 
1112
1113
  ## Email
@@ -1323,7 +1324,7 @@ Docs: `getting-started.md`. Code: `src/abstractruntime/core/runtime.py`, `src/ab
1323
1324
  ## How do I run a workflow on a schedule or on request?
1324
1325
 
1325
1326
  Create an automation. An automation is a durable controller run that starts the target workflow as a child run (an
1326
- occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`) or `manual@1` (run now only).
1327
+ occurrence) on each trigger: `schedule@1` (fixed UTC intervals such as `5m` or `24h`), `schedule@2` (the same intervals plus daily, weekly and monthly rules at a wall time in an IANA time zone, daylight-saving correct) or `manual@1` (run now only).
1327
1328
  `create_automation(...)` creates it, `apply_automation_command(...)` pauses, resumes, runs now, edits, stops the
1328
1329
  current occurrence, archives it or unarchives it (it comes back paused with its history), and the host drives it
1329
1330
  like any run (`drive_automation` does this in-process). Nothing is deleted: an archived automation keeps its
@@ -2480,6 +2481,7 @@ Lists accept a JSON array, a JSON array pasted as a string, or newline-separated
2480
2481
  - 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
2482
  - **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
2483
  - **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.
2484
+ - **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.
2483
2485
 
2484
2486
  ## Prompt-cache control plane and durable blocs
2485
2487
 
@@ -3022,8 +3024,14 @@ Public durable entry points:
3022
3024
  These helpers create child runs under an existing parent run and execute the real
3023
3025
  `LLM_CALL`, `TOOL_CALLS`, or stream finalization through Runtime rather than
3024
3026
  doing external work in host/controller code. `stream_voice(...)` yields TTS
3025
- stream events for progressive playback and completes the child run with the
3026
- final audio artifact when the stream succeeds.
3027
+ stream events for progressive playback; it is never a wait: nothing durable
3028
+ exists while audio streams, and when the stream ends (done, error, cancel or
3029
+ the consumer closing it) the child run is created already completed with the
3030
+ outcome (the final audio artifact on success). The child's id is announced up
3031
+ front in the `runtime_start` event (`child_run_id`). A host that finds a
3032
+ streamed-speech wait left by a runtime before this behaviour
3033
+ (`is_interrupted_voice_stream_wait`) closes it with
3034
+ `close_interrupted_voice_stream(child_run_id, reason=...)`.
3027
3035
 
3028
3036
  Example:
3029
3037
 
@@ -3599,7 +3607,7 @@ sources), `abstractruntime.automation_queries` (listing), `abstractruntime.sessi
3599
3607
 
3600
3608
  ```mermaid
3601
3609
  flowchart LR
3602
- 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"]
3610
+ Trigger["Trigger source<br/>schedule@1 / schedule@2 / manual@1"] -->|"due tick or run now"| Controller["Controller run<br/>(automation id)<br/>vars._meta.automation<br/>vars._runtime.automation"]
3603
3611
  Commands["apply_automation_command<br/>pause / resume / run_now /<br/>revise / stop_current / archive / unarchive"] -->|"decision + wake"| Controller
3604
3612
  Controller -->|"START_SUBWORKFLOW<br/>deterministic run_id"| Occurrence["Occurrence run<br/>role: occurrence<br/>(a session turn)"]
3605
3613
  Occurrence --> Descendants["Descendant runs<br/>role: descendant"]
@@ -3738,6 +3746,35 @@ Config: `{start_at?, every?, until?, count?, anchor?}`.
3738
3746
  - The event id of a scheduled tick is `schedule@1:<binding_id>:<tick>`. A revision that changes the trigger gets a
3739
3747
  new `binding_id`, so the new schedule never reuses an old event id.
3740
3748
 
3749
+ ### `schedule@2`
3750
+
3751
+ `schedule@2` adds calendar rules on wall time in a time zone. `schedule@1` stays registered and unchanged: its
3752
+ configs normalize byte for byte as before and its automations keep their tick grid. Use `schedule@2` for new
3753
+ automations.
3754
+
3755
+ Config: `{kind, at?, days?, day?, time_zone?, start_at?, every?, until?, count?}`. The normalized config always
3756
+ carries `kind`, then the rule fields, `time_zone`, `start_at`, `anchor` (= `start_at`) and the bounds.
3757
+
3758
+ | `kind` | Rule fields | Meaning |
3759
+ | --- | --- | --- |
3760
+ | `every` | `every` (`8h`, `7d`, ...) | Exactly `schedule@1`'s fixed UTC interval from `start_at`. `time_zone` is optional and only labels the schedule. |
3761
+ | `once` | `start_at`, or `at: "YYYY-MM-DDTHH:MM"` with `time_zone` | One run. A wall time `at` is converted to `start_at` in `time_zone`. |
3762
+ | `daily` | `at: "HH:MM"` | Every day at that wall time. |
3763
+ | `weekly` | `days` (non-empty subset of `mon`..`sun`), `at` | Those weekdays at that wall time. `days` is normalized to Monday-first order without duplicates. |
3764
+ | `monthly` | `day` (1..31 or `"last"`), `at` | That day of each month; a day beyond the month's length runs on the month's last day (day 31 runs on 28 or 29 February). |
3765
+
3766
+ - Calendar rules (`daily`, `weekly`, `monthly`) require `time_zone`, an IANA name such as `Europe/Paris`
3767
+ (`validate_time_zone(name)`; `time_zone_names()` lists the names the host knows). They take no `every`.
3768
+ - Wall times convert to UTC with `zoneinfo`. A wall time that does not exist that day (spring forward) runs at the
3769
+ shifted instant: a 02:30 rule runs at 03:30 on that day and at 02:30 afterwards. A wall time that happens twice
3770
+ (fall back) runs once, at its first occurrence. A daily 08:00 stays at 08:00 local time across both transitions.
3771
+ - Tick 0 is the first rule time at or after `start_at` (default: the creation time). `count` and `until` bound the
3772
+ ticks as in `schedule@1`.
3773
+ - Missed ticks coalesce and a resume after a pause skips the ticks that passed, exactly as in `schedule@1`. The event
3774
+ id of a tick is `schedule@2:<binding_id>:<tick>`.
3775
+ - Every instant is computed from its tick index in constant time, so an automation that was down for years catches up
3776
+ with one occurrence without walking the missed ticks.
3777
+
3741
3778
  ### `manual@1`
3742
3779
 
3743
3780
  Config: `{}`. The automation runs only when asked with `automation.run_now`. A manual run of any automation, whatever
@@ -4246,9 +4283,9 @@ receives its result directly.
4246
4283
 
4247
4284
  ## Limits in v1
4248
4285
 
4249
- - Schedules are fixed UTC intervals (`s`, `m`, `h`, `d`, at most `366d`). There are no cron expressions, calendar
4250
- months, time zones or daylight-saving rules, and `anchor` must equal `start_at`.
4251
- - The shipped trigger sources are `schedule@1`, `manual@1` and `email.received@1`. There is no generic external
4286
+ - Schedules are fixed UTC intervals (`schedule@1`, `schedule@2` `every`) or daily, weekly and monthly wall-time rules
4287
+ in an IANA time zone (`schedule@2`). There are no cron expressions, and `anchor` must equal `start_at`.
4288
+ - The shipped trigger sources are `schedule@1`, `schedule@2`, `manual@1` and `email.received@1`. There is no generic external
4252
4289
  event source yet.
4253
4290
  - Occurrences run one at a time (`serial`), missed ticks coalesce, and a failed occurrence never stops the
4254
4291
  automation (`failure: "continue"`). These policies cannot be changed.
@@ -5887,7 +5924,7 @@ In this repo, the AbstractCore wiring lives under `src/abstractruntime/integrati
5887
5924
 
5888
5925
  ## Features (reference)
5889
5926
 
5890
- - `automations.md` — automations: a workflow run on a schedule or on request as a durable controller run; triggers (`schedule@1`, `manual@1`, `email.received@1`, entry-point sources), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
5927
+ - `automations.md` — automations: a workflow run on a schedule or on request as a durable controller run; triggers (`schedule@1`, `schedule@2` calendar rules in a time zone, `manual@1`, `email.received@1`, entry-point sources), commands, independent or growing context, discussions forked at any occurrence (own writable workspace, the automation's workspace mounted read-only), tool approval, typed waits, notifications and retries, and the storage guarantees (create-if-absent, per-run lock, turn roots, session kinds, one writer process per store)
5891
5928
  - `entity-runtime.md` — per-entity runtimes for summoned entities: homes, the one-writer lease, act-only diary privacy (`$act_only` refs), durable visit waits with deadlines
5892
5929
  - `evidence.md` — artifact-backed evidence capture for external-boundary tools
5893
5930
  - `mcp-worker.md` — MCP worker CLI (`abstractruntime-mcp-worker`)
@@ -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.9.0
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`)
@@ -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, 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
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), `schedule@2` (the same plus daily/weekly/monthly wall-time rules in an IANA time zone, DST-correct) 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.9.0"
7
+ version = "0.10.0"
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,11 @@ 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.25.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
+ # 2.26.0: `abstractcore.config.recommendations.voice_input_hint`, served through
59
+ # `config_facade.voice_input_hint` (the speech-input row's hint; round 16).
60
+ "abstractcore>=2.26.0",
57
61
  "openai<3.0.0,>=1.109.1",
58
62
  "httpx<1.0.0,>=0.28.1",
59
63
  "anyio<5.0.0,>=4.12.1",
@@ -70,12 +74,12 @@ dependencies = [
70
74
 
71
75
  [project.optional-dependencies]
72
76
  apple = [
73
- "abstractcore[apple]>=2.25.0",
77
+ "abstractcore[apple]>=2.26.0",
74
78
  "setuptools<82.0.0,>=80.10.2",
75
79
  ]
76
80
 
77
81
  gpu = [
78
- "abstractcore[gpu]>=2.25.0",
82
+ "abstractcore[gpu]>=2.26.0",
79
83
  # vLLM 0.9-0.19 caps setuptools below 80; 77.0.3 is still a modern floor.
80
84
  "setuptools<82.0.0,>=77.0.3",
81
85
  ]
@@ -0,0 +1,20 @@
1
+ ### Added
2
+
3
+ - Trigger source `schedule@2`: `{kind: "daily", at: "HH:MM"}`, `{kind: "weekly", days: [...], at}` and `{kind: "monthly", day: 1..31 | "last", at}` evaluated on wall time in the config's `time_zone` (IANA, converted with `zoneinfo`: a skipped wall time runs at the shifted instant, a repeated one runs once; a day beyond the month's length runs on its last day), plus `{kind: "every"}` and `{kind: "once"}` with `schedule@1`'s meaning (a `once` may give a wall time `at` in `time_zone`). Same coalescing and pause policy as `schedule@1`; event ids `schedule@2:<binding_id>:<tick>`. `validate_time_zone(name)` and `time_zone_names()` are exported from `abstractruntime.triggers`. See `docs/automations.md`.
4
+ - `integrations.abstractcore.config_facade.voice_input_hint(route, host=None)`: AbstractCore's served one-line hint for a configured speech-input route (`abstractcore.config.recommendations.voice_input_hint`, AbstractCore >= 2.26.0), so a host such as AbstractGateway serves it without importing AbstractCore itself. The AbstractCore floor is 2.26.0.
5
+ - A limit on an execution wire: `edge.data.loopLimit = {"max": N}` (the editor's ↺N badge on a wire that makes execution repeat). Before compile, `visual/loop_limit_lowering.py` turns it into a `loop_limit` node on that wire (`again` to the wire's target; `limit_reached` to the other branch when the wire leaves an If/Else and that branch is not itself a limited wire, else nothing: the path ends at the limit), re-keying the target's per-path values and entry list. A run tree shows the lowered node as "Loop limit N". `VisualEdge` now carries `data` (older runtimes never read it, so a limited flow runs unlimited there).
6
+ - VisualFlow `get_vars` node (Get Variables): a data node with one output per variable, its pin id the variable name (dotted paths allowed); each output reads the run variable's current value, or null when it is not set.
7
+ - VisualFlow `loop_limit` node (Loop Limit): exec outputs `again` (taken while fewer than `max` passes were let through) and `limit_reached` (then the count starts again from 0), data output `count` (the pass number). The count lives in `run.vars._temp.loop_limits.<node id>`, so it survives pause/resume. It belongs to the current iteration of the enclosing ForEach / For / While (each item, and each new entry of that loop, starts from 0); with no enclosing loop, to the run. Its `max` comes only from its own pin, never from the previous step's output.
8
+ - VisualFlow `add_to_list` node (Add to List Variable): `name`, `item` (added as one element), `items` (each element added); a missing or null variable starts as `[]`; a variable that holds something else, or `items` that is not a list, fails the step naming it; reads and writes in one step; output `list`.
9
+ - String Template: a placeholder reads an input pin of its name, then the `vars` object, then the run variable (top-level names not starting with `_`). A list or object with no filter is written as JSON (it was Python's `str()`).
10
+
11
+ ### Changed
12
+
13
+ - An execution wire that loops back out of a ForEach / For / While body (from inside the body to the loop node itself or to anything before it) is refused when the flow compiles: "Wire <source>.<pin> -> <target> goes back out of <loop>'s loop body: the run would never end. A path inside a loop body can only repeat within the body; to repeat the whole loop, wire the loop-back after the loop's done." Such a wire re-entered the loop with its frame still on the control stack, so the stack grew by one frame per pass and the run never ended (a Loop Limit on it never reached its max). A loop-back that goes through the loop's `done`, or that stays inside the body, is unchanged (`visual/loop_back_check.py`).
14
+ - `schedule@1` is unchanged: its configs normalize byte for byte as before and existing automations keep their tick grid (`tests/test_schedule_v1_corpus.py` freezes the 0.9.1 answers on real automation configs).
15
+
16
+ ### Fixed
17
+
18
+ - Set Variables (and Add to List Variable) only take what their own pins carry (a wire, a value set on the node, an expression). Before, keys of the previous step's output were written as variables too.
19
+ - Set Variables (`set_vars`): every data input pin besides `updates` is one variable, written under the pin's id (dotted paths nest) with its value: a wire, else the pin's default. These win over the same name in the `updates` object. AbstractFlow edits them as rows (name, type, value), so one node initialises several variables, wired or literal. A flow using such rows needs this runtime: an older one writes only `updates`. Test: `tests/test_visual_set_vars_pins.py`.
20
+ - VisualFlow reroute ("relay") nodes: a dot in AbstractFlow that lets one output feed several inputs along a tidy path. They are visual only: before compiling, every chain `source -> reroute (-> reroute ...) -> target` is rewired `source -> target` and the reroutes are removed (`visualflow_compiler/visual/reroute_lowering.py`, run before the multi-entry lowering). A reroute with no source feeds nothing (its targets keep their defaults); per-path values that name a reroute point at its real source. Data wires only: an execution wire through a reroute, a second input into one, or a cycle of reroutes is refused with a message naming the wire. A flow with a connected reroute needs this runtime (older ones refuse the unknown node type). Test: `tests/test_visual_reroute_lowering.py`.
@@ -46,8 +46,10 @@ from .discovery_facade import (
46
46
  get_abstractcore_discovery_facade,
47
47
  )
48
48
  from .run_facade import (
49
+ LEGACY_VOICE_STREAM_WAIT_KEY_PREFIX,
49
50
  AbstractCoreRunFacade,
50
51
  get_abstractcore_run_facade,
52
+ is_interrupted_voice_stream_wait,
51
53
  )
52
54
  from .telegram_facade import (
53
55
  TelegramTdlibNotAvailable,
@@ -108,6 +110,8 @@ __all__ = [
108
110
  "ResponseFormatError",
109
111
  "get_global_telegram_client",
110
112
  "get_abstractcore_run_facade",
113
+ "is_interrupted_voice_stream_wait",
114
+ "LEGACY_VOICE_STREAM_WAIT_KEY_PREFIX",
111
115
  "create_local_runtime",
112
116
  "create_remote_runtime",
113
117
  "create_hybrid_runtime",
@@ -11,6 +11,7 @@ Scope:
11
11
  use scoped per-principal config files)
12
12
  - resolve the effective AbstractCore config file path
13
13
  - enumerate capability-default route specs (the catalog of known routes)
14
+ - the served speech-input hint for a configured route (`voice_input_hint`, AbstractCore >= 2.26.0)
14
15
  - read a provider API key from a specific AbstractCore config file
15
16
  - read AbstractCore's stored mail (IMAP/SMTP) and maintenance-triage settings
16
17
  - model weights: availability probes and single downloads (`model_materializer`)
@@ -221,6 +222,30 @@ def recommended_capability_selectors() -> List[str]:
221
222
  return []
222
223
 
223
224
 
225
+ def voice_input_hint(
226
+ route: Dict[str, Any], host: Optional[Dict[str, Any]] = None
227
+ ) -> Optional[Dict[str, Any]]:
228
+ """AbstractCore's served one-line hint for a CONFIGURED speech-input route, or None.
229
+
230
+ `abstractcore.config.recommendations.voice_input_hint` (AbstractCore >= 2.26.0):
231
+ THE sentence clients show next to the Voice input row, verbatim -- for example
232
+ a faster-whisper route on Apple silicon runs on the processor while mlx-whisper
233
+ runs the same model on the GPU. Computed from the host and the installed
234
+ engines, never in a client; it never changes the route. Raises when
235
+ AbstractCore is too old: a host serving the speech-input row without its hint
236
+ would be a silent regression.
237
+ """
238
+ try:
239
+ from abstractcore.config.recommendations import voice_input_hint as _core_voice_input_hint
240
+ except Exception as exc:
241
+ raise RuntimeError(
242
+ "AbstractCore's speech-input hint is unavailable "
243
+ "(abstractcore.config.recommendations.voice_input_hint needs AbstractCore >= 2.26.0)."
244
+ ) from exc
245
+ answer = _core_voice_input_hint(dict(route), host)
246
+ return dict(answer) if answer else None
247
+
248
+
224
249
  def capability_default_specs() -> Dict[str, Dict[str, Any]]:
225
250
  """Return {route_key -> spec dict} for all known capability-default routes."""
226
251
  try: