AbstractRuntime 0.8.1__tar.gz → 0.8.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/CHANGELOG.md +31 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/PKG-INFO +3 -3
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/README.md +2 -2
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/architecture.md +2 -2
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/automations.md +1 -1
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/llms-full.txt +5 -5
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/llms.txt +1 -1
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/pyproject.toml +1 -1
- abstractruntime-0.8.3/release-notes.md +11 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/commands.py +12 -3
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/controller.py +28 -4
- abstractruntime-0.8.3/src/abstractruntime/integrations/abstractcore/mcp_facade.py +120 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_commands.py +66 -0
- abstractruntime-0.8.3/tests/test_mcp_runs_untrusted_and_facade.py +119 -0
- abstractruntime-0.8.1/release-notes.md +0 -33
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/.github/workflows/ci.yml +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/.github/workflows/release.yml +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/.gitignore +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/ACKNOWLEDGMENTS.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/CODE_OF_CONDUCT.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/CONTRIBUTING.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/LICENSE +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/ROADMAP.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/SECURITY.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0001_layered_coupling_with_abstractcore.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0002_execution_modes_local_remote_hybrid.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0003_provenance_tamper_evident_hash_chain.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0004_runtime_owns_run_scoped_media_execution_truth.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0005_runtime_owns_abstractcore_host_discovery_queries.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0006_runtime_owns_durable_abstractcore_bloc_prompt_cache.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/0007_runtime_relays_core_owned_model_residency_truth.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/adr/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/api.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/artifacts.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/001_runtime_kernel.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0030_runtime_host_facades_for_comms_telegram_and_tool_specs.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0032_runtime_durable_outbound_comms_truth.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0033_runtime_host_local_prompt_cache_export_import_surface.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0035_model_residency_provider_truth_for_local_http_clients.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0037_visualflow_generate_music_node_compiler_parity.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0039_runtime_music_structure_prompt_bool_contract.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/003_wait_primitives.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0040_task_agnostic_local_residency_listing.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0041_runtime_hardware_extras_avoid_nonpermissive_document_stacks.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0042_core_vision_upscale_and_parameter_surface.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0043_runtime_vision_adapter_and_batch_surface.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/004_scheduler_driver.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/005_abstractcore_integration.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/006_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/007_provenance_hash_chain.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/009_artifact_store.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/010_examples_and_composition.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/011_subworkflow_support.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/013_effect_retries_and_idempotency.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/016_runtime_aware_parameters.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/019_runtime_host_facade_for_core_operator_surfaces.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/020_runtime_gateway_install_boundary.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/021_runtime_gateway_env_namespace_cleanup.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/022_model_residency_control_plane.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/023_truthful_local_media_residency_boundaries.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/024_runtime_owned_run_scoped_media_execution.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/026_runtime_host_discovery_facade_for_core_catalogs.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/027_runtime_durable_bloc_prompt_cache_facade.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/028_runtime_bloc_kv_lifecycle_and_pruning.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/029_runtime_music_generation_and_discovery_via_abstractcore.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0846_mlx_instance_scheduling_and_execution_controls.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/completed/0847_automations_v1_controller_contracts_occurrences_triggers.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/001_integrations_abstractcore.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/001_runtime_kernel.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/002_persistence_and_ledger.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/002_snapshots_bookmarks.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/0034_agent_runtime_convenience_constructor.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/003_provenance_ledger_chain.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/004_tests.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/005_docs_updates.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/005_examples_and_composition.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/DEPRECATED_README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/0070_standalone_wui_browser_session_security_contract.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/008_signatures_and_keys.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/014_remote_tool_worker_executor.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/017_limit_warnings_and_observability.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/018_workspace_access_policy_for_media_and_tools.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/0233_real_run_cancellation.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/025_runtime_retention_and_purge_contract.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/026_context_checkpoint_self_compression.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/027_quote_provenance_discipline.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/028_selective_artifact_rehydration.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/0845_session_prompt_cache_resume_and_purge_contract.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/0848_automations_v2_external_event_inbox_and_run_triggers.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_portability/0065_portable_process_and_lock_layer.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_portability/0066_portable_io_and_media_reader.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_portability/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0044_meta_analysis_record.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0045_crash_replay_harness_and_ordering_invariant.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0046_per_run_driver_exclusion.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0047_indexed_idempotency_lookup.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0048_durable_io_unification.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0049_llm_client_mechanical_split.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0050_control_sidecar_all_writers.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0051_runtime_owned_durable_event_mailbox.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0052_sync_store_event_loop_tripwire.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0053_bounded_run_vars_growth.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0054_runtime_health_counters.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0055_jsonl_store_honesty.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0064_prompt_cache_fingerprint_stability.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0067_durable_write_discipline.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/0068_hot_path_store_reads.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/planned/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/0031_runtime_tool_spec_adapters_for_gateway_and_mcp.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/0036_local_media_residency_bridge_to_core_residency.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/0038_core_server_pool_residency_affinity.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/0069_document_renderer_professional_figures.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0056_schema_version_and_quarantine_loading.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0057_trust_boundary_stamp_registry.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0058_terminal_run_archival_helper.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0059_memory_span_handler_extraction.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0060_visualflow_compiler_decomposition.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0061_root_api_deprecation_machinery.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0062_dependency_honesty_extras.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/0063_b3_envelope_lane_unification.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/backlog/proposed/runtime_systemic_reliability/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/email.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/entity-runtime.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/evidence.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/faq.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/getting-started.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/integrations/abstractcore.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/limits.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/manual_testing.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/mcp-worker.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/proposal.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/provenance.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/snapshots.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/tool-approval.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/tools-comms.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/troubleshooting.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/docs/workflow-bundles.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/01_hello_world.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/02_ask_user.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/03_wait_until.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/04_multi_step.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/05_persistence.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/06_llm_integration.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/07_react_agent.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/examples/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/mkdocs.yml +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/pytest.ini +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/scripts/backfill_diary_edges.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/scripts/generate_llms_full.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automation_queries.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/adapters.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/attention.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/bundle.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/bundles/automation-controller/flows/controller.json +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/bundles/automation-controller/manifest.json +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/ledger.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/models.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/service.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/config.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/effect_cancellation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/event_keys.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/health.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/live_deltas.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/models.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/progress_channel.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/run_attribution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/run_identity.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/run_lifecycle.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/runtime.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/spec.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/tool_scope.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/core/vars.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/documents/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/documents/charts.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/documents/docx.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/documents/pdf.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/actions.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/automations.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/binding.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/feeder.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/frame.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/email/inbox.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/evidence/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/evidence/recorder.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/history_bundle.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/act_only.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/chat.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/communities.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/diary.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/digest.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/entity_runtime.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/fingerprint.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/lease.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/life.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/memory_reader.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/night_voice.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/phase_graph.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/phase_spec.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/prelude.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/prompt_overlay.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/reflection.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/spec/entity_phases.vendored.json +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/substrate.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/tool_effects.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/tool_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/identity/visit_workflow.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/agora_tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/comms_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/config_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/constants.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/data_registry_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/default_tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/discovery_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/discovery_queries.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/effect_handlers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/email_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/embeddings_client.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/factory.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/host_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/llm_client.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/local_helper_tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/logging.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/mcp_worker.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/media_subprocess.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/observability.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/output_specs.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/run_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/session_attachments.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/summarizer.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/telegram_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/tool_effects.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/tool_executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/tool_inventory_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractcore/workspace_scoped_tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractmemory/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractmemory/brain_handlers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractmemory/effect_handlers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractmemory/identity_support.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/integrations/abstractmemory/seam_handlers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/active_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/active_memory.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/compaction.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/kg_packets.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/memact_composer.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/recall_levels.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/memory/token_budget.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/rendering/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/rendering/agent_trace_report.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/rendering/json_stringify.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/scheduler/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/scheduler/convenience.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/scheduler/multi_store.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/scheduler/registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/scheduler/scheduler.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/session_history.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/session_turns.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/artifacts.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/base.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/commands.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/in_memory.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/json_files.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/lease.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/ledger_chain.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/ledger_slim.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/observable.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/offloading.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/serialize.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/snapshots.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/sqlite.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/storage/steer_sidecar.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/email_received.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/manual.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/protocol.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/triggers/schedule.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/turn_grounding.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/utils/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/utils/atomic_files.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/utils/file_filters.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/utils/workspace_paths.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/agent_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/context_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/control_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/effect_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/event_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/function_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/memact_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/subflow_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/adapters/variable_adapter.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/compiler.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/flow.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/agent_ids.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/builtins.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/code_executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/execution_metrics.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/function_library.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/models.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/multi_entry_lowering.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/visualflow_compiler/visual/pin_expressions.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/workflow_bundle/__init__.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/workflow_bundle/models.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/workflow_bundle/packer.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/workflow_bundle/reader.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/workflow_bundle/registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/README.md +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/automation_harness.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/conftest.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/email_wp2_support.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/live_email/conftest.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/live_email/live_email_support.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/live_email/test_email_live_runtime.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_abstractcore_comms_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_abstractcore_discovery_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_abstractcore_host_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_abstractcore_run_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_abstractcore_telegram_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_active_context_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_active_memory.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_agora_agent_alias_identity.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_agora_tools_http.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_analyze_media_addressing_and_walling.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_answer_user_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_artifacts.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_controller.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_controller_recovery.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_definition.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_discussion_isolation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_growing_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_index.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_next_fire.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_occurrence_recovery.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_replay_read_only.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_retry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_session_turns.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_status.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_automation_tool_approval.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_browser_probe_target_walling.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_budget_law_no_unrequested_caps.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_capability_default_reasoning.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_chat_summarizer_integration.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_code_node_restricted_python.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_command_store.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_compaction_helpers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_compaction_summarizer_route.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_config_facade_models_engines.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_control_adapter_while.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_controller_bundle_packaged.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_crash_ordering_inversions.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_create_if_absent.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_data_registry_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_camera_gating.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_comms_gating.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_include_skim_files.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_include_skim_folders.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_include_skim_web.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_default_tools_search_files_executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_diary_capture.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_diary_write_rescue.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_directory_lease.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_disabled_toolsets_seam.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_discovery_survives_unbuildable_default.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_discovery_tts_unavailable_reason.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_discovery_voice_openai_api_key.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_discussion_session_anchor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_document_markdown_tables.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_document_renderers_hr_quote.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_durable_toolsets.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_durable_write_discipline.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_e2e_tool_calls_idempotency_lmstudio.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_effect_cancellation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_effect_issuance_idempotency.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_effect_payload_stays_json_serializable.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_election_consequence_teaching.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_binding_and_refiner.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_gate_fixes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_inbox_and_trigger.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_regate_fixes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_review_fixes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_self_trigger_loop.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_email_toolset_and_walls.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_emergence_experiment.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_emit_event_uses_wait_index.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_emit_event_without_workflow_registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_endpoint_profile_route_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_awake_memory_fixes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_brain_effects.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_chat_driver.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_chat_tools_reflection.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_diary.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_execute_tool.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_fetch_url_tool.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_history_window.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_life_loop.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_memory_richness.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_phase_graph_conformance.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_react_visit_window.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_recent_memories.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_runtime.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_search_memory.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_sleep_bound_and_yield_attribution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_substrate_resolution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_visit_honesty.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_workspace_cap.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_entity_workspace_tools.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_event_wait_index.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_every_path_bearing_tool_is_walled.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_evidence_recorder.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_evidence_recorder_post_policy_envelope.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_execute_command_output_offload.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_execution_capability_discovery.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_explicit_eject_other_clients.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_factory_default_retry_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_factory_timeouts_default_to_abstractcore_config.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_format_repair_nudge.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_fresh_install_no_provider.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_gateway_facades_c4899.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_git_read_only_refiner.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_hf_process_residency_merge.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_history_window_multimodal.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_hot_path_store_reads.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_indexed_idempotency_lookup.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_integration_abstractcore.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_integrations_abstractcore.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_json_file_run_store_children_index.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_json_run_cache_bound.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_json_store_scan_memo.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_jsonl_ledger_recovery.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_kg_learn_and_recall_contract.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_ledger_chain.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_ledger_record_slimming.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_ledger_subscription.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_live_token_deltas.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_media_artifact_refs.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_media_artifact_refs_persist_across_restart.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_media_uses_source_path_label.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_payload_shape_refusal.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_requires_prompt.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_response_schema_normalization.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_structured_output_fallback.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_text_phase_progress.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_truncation_retry_contract.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_use_context_appends_turn.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_call_verbatim_payload_capture.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_client_grounding_tail.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_client_media_artifacts.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_client_system_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_client_tool_call_parsing.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_retry_classification.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_llm_streaming_on_token.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_local_helper_tool_exposure.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_local_residency_host_sweep.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_local_runtime_timeout_kwarg_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_max_iterations_ceiling.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mcp_remote_tool_executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mcp_worker_logging.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mcp_worker_security.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mcp_worker_stdio.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_media_artifact_resolution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_media_capability_default_routing.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_media_only_requests_skip_text_client.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_media_subprocess.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memact_composer_from_kg_result.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_appraise_handler.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_communities.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_assert_attributes_defaults.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_packets.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_predicate_aliasing.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_query_packetization_restart.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_query_recall_level_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_kg_semantic_query_ranking.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_note_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_query_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_query_rich_filters.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_scope_and_rehydrate_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_seam_handlers.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_seam_sqlite_durability.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_memory_tag_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mlx_generation_serialization.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_mlx_process_residency_merge.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_model_eject_cancel.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_model_residency_clean_switch.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_model_residency_control_plane.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_model_residency_lock_and_context_estimate.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_multi_store_scheduler.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_multimodal_abstractcore_integration.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_native_mlx_application_wiring.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_native_mlx_execution_controls_live.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_native_tool_channel.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_night_voice.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_no_default_provider_refusal_ux.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_offload_answer_chain_c4978.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_offloaded_node_traces_report_unknown_not_zero.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_offloading.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_packaging_extras.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_parallel_readonly_tool_execution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_pause_resume.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_pdf_unicode_rendering.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_personal_cycle.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_phantom_attachment_index.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_phase_graph_artifact_control.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_phase_graph_obedience.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_phase_vocabulary_migration.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_pooled_client_strips_construction_cache_key.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_cache_export_import.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_cache_fingerprint_stability.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_cache_modules.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_cache_posture_inheritance.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_cache_thinking_and_prompt_only.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_prompt_overlay.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_provider_endpoint_profile_resolution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_provider_pin_routing_isolation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_queryable_run_store.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_read_file_fallback_to_session_attachments.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_read_idle_threading.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_readoption_experiment.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_real_integration.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_realize_election.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_recall_levels_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_remote_client_cancel.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_remote_llm_client.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_remote_speculation_defaults.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_rendering_agent_trace_report.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_rendering_json_stringify.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_report_branding.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_resident_media_generation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_resume_concurrent_same_wait.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_retry_idempotency.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_run_history_bundle.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_run_index_workspace_root.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_run_mutation_lock.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_run_scoped_tool_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_run_tool_scope_ceiling.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_browser_session_boundary.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_config_max_output_tokens_fallback.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_default_provider_model_refresh.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_effect_invocation_trace.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_health_and_bounded_vars.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_install_boundary.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_llm_call_grounding_in_ledger.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_node_traces.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_start_seeds_tool_support.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_runtime_tick_step_gate.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_scheduler.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_send_email_refiner.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_send_email_self_default_policy.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_attachments_registry_and_open_tool.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_history.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_prompt_cache_attribution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_prompt_cache_visibility.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_route_stamp.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_session_start_cost.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_shell_tool_exposure.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_snapshots.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_speculation_inheritance.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_speculation_reaches_provider_construction.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_sqlite_ledger_store.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_start_subworkflow_async_wait.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_start_subworkflow_inherit_context_merges_messages.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_start_subworkflow_workspace_inheritance.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_steer_sidecar.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_storage_deletion.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_structured_output_schema_enum.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_subworkflow.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_terminal_effect_completion.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_terminal_resume_appends_ledger_completion.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_thinking_inheritance.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tick_completion_includes_output_in_ledger.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_approval_executor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_approval_resume_executes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_approval_wait_key_identity.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_calls_idempotency_keys.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_catalog.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_descriptor_registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_argument_sanitization.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_error_output_detection.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_filename_alias.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_kwarg_canonicalization.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_read_file_aliases.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_executor_timeout.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_inventory_facade.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_invoke_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_policy_and_mounts.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_tool_wait_allowlist_safety.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_topic_election_world_model.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_trace_context_propagation.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_trigger_registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_trigger_schedule_math.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_turn_grounding_byte_stability.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_turn_grounding_carriers_a3.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_vars_query_effect.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visit_ab_fixture.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visit_midturn_elections.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visit_midturn_resume.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visit_workflow.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_output_context_includes_messages.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_skills_block_passthrough.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_tool_observations_persist_across_restart.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_use_context_inherits_attachments.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_use_context_persists_tool_observations.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_agent_use_context_persists_turn.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_entity_memory_nodes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_flow_end_effect_only_persistence.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_llm_call_partial_override.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_llm_call_schema_ref_resolution.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_memact_compose_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_memory_kg_query_outputs_propagate.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_memory_kg_resolve_outputs_propagate.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_multi_entry_loop_overrides.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_unknown_node_type_refuses.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visual_wait_event_deadline_passthrough.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_add_message_builtin.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_add_message_node_appends_to_active_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_agora_react_agent.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_call_tool_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_capability_routes_and_thinking.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_compiler_basic.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_context_and_builder_nodes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_continue_on_error.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_edit_json_schema_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_event_inbox_react_agent.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_file_nodes_workspace.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_function_library.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_get_element_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_get_random_element_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_get_var_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_has_tools_builtin.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_llm_call_context_attachments_map_to_media.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_llm_call_multimodal_output.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_make_object_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_media_nodes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_memory_effect_nodes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_memory_source_pins.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_pin_expressions.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_prompt_only.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_random_nodes.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_schema_enum_switch.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_string_contains_replace.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_visualflow_tool_parameters_node.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_voice_openai_api_key_path.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_w4_feelings_lens.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_wait_event_deadline.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_wait_event_prompt_metadata.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_wait_until_streak.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_wait_until_utc_normalization.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workflow_bundle_registry.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_builtin_deny.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_policy_absolute_reanchor.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_policy_allowlist_mode.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_policy_mount_virtual_paths.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_policy_tool_calls_persist_across_restart.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_prompt_context.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_workspace_read_only.py +0 -0
- {abstractruntime-0.8.1 → abstractruntime-0.8.3}/tests/test_write_chart.py +0 -0
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
Nothing yet.
|
|
11
|
+
|
|
12
|
+
## [0.8.3] - 2026-10-01
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `integrations.abstractcore.mcp_facade`: opens a stdio or HTTP MCP client (a stdio server starts
|
|
18
|
+
with exactly the environment given), turns a server's tool into an `mcp::<server>::<tool>` spec
|
|
19
|
+
without its URL, and runs `tools/call` with the runtime's result mapping. The gateway calls
|
|
20
|
+
registered MCP servers through it.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- An automation run started by an email from someone else (untrusted input) is never offered an MCP
|
|
25
|
+
tool: every `mcp::...` name leaves its tool lists and is never granted, even when named.
|
|
26
|
+
|
|
27
|
+
## [0.8.2] - 2026-10-01
|
|
28
|
+
|
|
29
|
+
Pausing an automation also stops its retries. Requires AbstractCore 2.20.2 (unchanged).
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- `automation.pause` also stops retries: an occurrence waiting in retry backoff is cancelled
|
|
33
|
+
(quietly, like `stop_current`), and a scheduled attempt that fails while the automation is paused
|
|
34
|
+
completes `failed` without a retry. An attempt already running still finishes, and a manual run
|
|
35
|
+
(`run_now`, allowed while paused) keeps its retries.
|
|
36
|
+
|
|
37
|
+
### Notes
|
|
38
|
+
- A retry that is waiting in backoff when you pause an automation is cancelled instead of starting
|
|
39
|
+
after its backoff. Resume the automation, or use `run_now`, to run it again.
|
|
40
|
+
|
|
10
41
|
## [0.8.1] - 2026-09-30
|
|
11
42
|
|
|
12
43
|
Email automations never trigger themselves, speech and images work without a buildable text model,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: AbstractRuntime
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
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
|
|
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
|
|
|
55
55
|
|
|
56
56
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
57
57
|
|
|
58
|
-
**Version:** 0.8.
|
|
58
|
+
**Version:** 0.8.2 • **Python:** 3.10+
|
|
59
59
|
|
|
60
60
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
61
61
|
|
|
@@ -147,7 +147,7 @@ state = rt.resume(
|
|
|
147
147
|
assert state.status.value == "completed"
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
## What’s included (v0.8.
|
|
150
|
+
## What’s included (v0.8.2)
|
|
151
151
|
|
|
152
152
|
Kernel (import-light):
|
|
153
153
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
6
6
|
|
|
7
|
-
**Version:** 0.8.
|
|
7
|
+
**Version:** 0.8.2 • **Python:** 3.10+
|
|
8
8
|
|
|
9
9
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
10
10
|
|
|
@@ -96,7 +96,7 @@ state = rt.resume(
|
|
|
96
96
|
assert state.status.value == "completed"
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
## What’s included (v0.8.
|
|
99
|
+
## What’s included (v0.8.2)
|
|
100
100
|
|
|
101
101
|
Kernel (import-light):
|
|
102
102
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AbstractRuntime — Architecture
|
|
2
2
|
|
|
3
|
-
> Updated: 2026-
|
|
4
|
-
> Version: 0.8.
|
|
3
|
+
> Updated: 2026-10-01
|
|
4
|
+
> Version: 0.8.2
|
|
5
5
|
> Scope: this describes **what is implemented in this repository**.
|
|
6
6
|
|
|
7
7
|
AbstractRuntime is a **durable workflow runtime**: it executes workflow graphs as a persisted state machine with explicit waits (user, time, events, jobs, subworkflows). A run can pause for hours/days and resume **without** keeping Python stacks/coroutines alive.
|
|
@@ -286,7 +286,7 @@ expected_revision=None, now=None)` is the only way to change an automation. It r
|
|
|
286
286
|
|
|
287
287
|
| Type | Effect | Rejected with |
|
|
288
288
|
|---|---|---|
|
|
289
|
-
| `automation.pause` | Stops **scheduled** admissions.
|
|
289
|
+
| `automation.pause` | Stops **scheduled** admissions. An attempt already running finishes, but no retry follows: an occurrence waiting in retry backoff is cancelled (quietly), and a scheduled attempt that fails while paused completes `failed` without a retry. `run_now` still works (a manual run keeps its retries). This is separate from the runtime's own pause. | `invalid_state` when archived or finished |
|
|
290
290
|
| `automation.resume` | Re-arms the schedule at the first tick after now. It never fires on resume and never catches up the paused time. Resuming an automation that is not paused is an applied no-op. | `invalid_state` when archived or finished |
|
|
291
291
|
| `automation.run_now` | Runs one occurrence at the controller's next step, even while paused (the automation stays paused). There is no queue. | `automation_busy` while an occurrence or a manual run is pending; `invalid_state` when archived, finished or exhausted |
|
|
292
292
|
| `automation.revise` | `payload.changes = {title?, target?, trigger?, context?, policy?}` (at least one). `title`, `target`, `trigger` and `context` are replaced whole; `policy` fields are merged, so a field you do not send keeps its value. The next revision applies from the controller's next step. A changed trigger gets a new binding and is re-armed after now, so no past tick fires; an unchanged trigger keeps its binding. | `invalid_state` when archived or finished; the definition's own reason codes for invalid changes |
|
|
@@ -53,7 +53,7 @@ See llms.txt for the linked index.
|
|
|
53
53
|
|
|
54
54
|
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
|
|
55
55
|
|
|
56
|
-
**Version:** 0.8.
|
|
56
|
+
**Version:** 0.8.2 • **Python:** 3.10+
|
|
57
57
|
|
|
58
58
|
**Status:** pre-1.0 (API may evolve). For production use, pin versions and follow `CHANGELOG.md`.
|
|
59
59
|
|
|
@@ -145,7 +145,7 @@ state = rt.resume(
|
|
|
145
145
|
assert state.status.value == "completed"
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
## What’s included (v0.8.
|
|
148
|
+
## What’s included (v0.8.2)
|
|
149
149
|
|
|
150
150
|
Kernel (import-light):
|
|
151
151
|
- workflow graphs: `WorkflowSpec` (`src/abstractruntime/core/spec.py`)
|
|
@@ -431,8 +431,8 @@ rt = create_local_runtime(provider="ollama", model="qwen3:4b")
|
|
|
431
431
|
|
|
432
432
|
# AbstractRuntime — Architecture
|
|
433
433
|
|
|
434
|
-
> Updated: 2026-
|
|
435
|
-
> Version: 0.8.
|
|
434
|
+
> Updated: 2026-10-01
|
|
435
|
+
> Version: 0.8.2
|
|
436
436
|
> Scope: this describes **what is implemented in this repository**.
|
|
437
437
|
|
|
438
438
|
AbstractRuntime is a **durable workflow runtime**: it executes workflow graphs as a persisted state machine with explicit waits (user, time, events, jobs, subworkflows). A run can pause for hours/days and resume **without** keeping Python stacks/coroutines alive.
|
|
@@ -3807,7 +3807,7 @@ expected_revision=None, now=None)` is the only way to change an automation. It r
|
|
|
3807
3807
|
|
|
3808
3808
|
| Type | Effect | Rejected with |
|
|
3809
3809
|
|---|---|---|
|
|
3810
|
-
| `automation.pause` | Stops **scheduled** admissions.
|
|
3810
|
+
| `automation.pause` | Stops **scheduled** admissions. An attempt already running finishes, but no retry follows: an occurrence waiting in retry backoff is cancelled (quietly), and a scheduled attempt that fails while paused completes `failed` without a retry. `run_now` still works (a manual run keeps its retries). This is separate from the runtime's own pause. | `invalid_state` when archived or finished |
|
|
3811
3811
|
| `automation.resume` | Re-arms the schedule at the first tick after now. It never fires on resume and never catches up the paused time. Resuming an automation that is not paused is an applied no-op. | `invalid_state` when archived or finished |
|
|
3812
3812
|
| `automation.run_now` | Runs one occurrence at the controller's next step, even while paused (the automation stays paused). There is no queue. | `automation_busy` while an occurrence or a manual run is pending; `invalid_state` when archived, finished or exhausted |
|
|
3813
3813
|
| `automation.revise` | `payload.changes = {title?, target?, trigger?, context?, policy?}` (at least one). `title`, `target`, `trigger` and `context` are replaced whole; `policy` fields are merged, so a field you do not send keeps its value. The next revision applies from the controller's next step. A changed trigger gets a new binding and is re-armed after now, so no past tick fires; an unchanged trigger keeps its binding. | `invalid_state` when archived or finished; the definition's own reason codes for invalid changes |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Durable workflow runtime (interrupt → checkpoint → resume) with an append-only execution ledger.
|
|
4
4
|
|
|
5
5
|
- Python: 3.10+ (see `pyproject.toml`)
|
|
6
|
-
- Version: 0.8.
|
|
6
|
+
- Version: 0.8.2
|
|
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.20.2 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`)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
### Added
|
|
2
|
+
|
|
3
|
+
- `integrations.abstractcore.mcp_facade`: opens a stdio or HTTP MCP client (a stdio server starts
|
|
4
|
+
with exactly the environment given), turns a server's tool into an `mcp::<server>::<tool>` spec
|
|
5
|
+
without its URL, and runs `tools/call` with the runtime's result mapping. The gateway calls
|
|
6
|
+
registered MCP servers through it.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- An automation run started by an email from someone else (untrusted input) is never offered an MCP
|
|
11
|
+
tool: every `mcp::...` name leaves its tool lists and is never granted, even when named.
|
|
@@ -13,8 +13,11 @@ record, controller wake, child cancellation), so a crash after the decision
|
|
|
13
13
|
never loses them. Domain rejections are returned, never raised.
|
|
14
14
|
|
|
15
15
|
Semantics:
|
|
16
|
-
- pause: gates SCHEDULED admission
|
|
17
|
-
|
|
16
|
+
- pause: gates SCHEDULED admission (never the runtime pause gate); an attempt
|
|
17
|
+
already running finishes, but no retry follows while paused: an occurrence
|
|
18
|
+
waiting in retry backoff is cancelled (quiet), and a scheduled attempt that
|
|
19
|
+
fails while paused completes `failed` without a retry. run_now stays allowed
|
|
20
|
+
(a manual occurrence started while paused keeps its retries).
|
|
18
21
|
- resume: re-arms the trigger at the first tick after now; never fires.
|
|
19
22
|
- run_now: records `manual_pending` (admitted at the controller's next
|
|
20
23
|
boundary); rejected `automation_busy` while an occurrence or a manual run is
|
|
@@ -91,7 +94,13 @@ def _decide(
|
|
|
91
94
|
if command_type == "automation.pause":
|
|
92
95
|
if archived or terminal:
|
|
93
96
|
return _reject("invalid_state", "An archived or finished automation cannot be paused.")
|
|
94
|
-
|
|
97
|
+
pause_state: Dict[str, Any] = {"paused": True}
|
|
98
|
+
pending = state.get("pending_occurrence")
|
|
99
|
+
if not state.get("paused") and isinstance(pending, dict) and pending.get("phase") == "backoff":
|
|
100
|
+
# A retry only waiting for its backoff never starts after a pause (N3): the
|
|
101
|
+
# occurrence is cancelled at the controller's next boundary, like stop_current.
|
|
102
|
+
pause_state["pending_occurrence"] = {**pending, "stop_requested": True}
|
|
103
|
+
return {"delta": {"state": pause_state}}
|
|
95
104
|
|
|
96
105
|
if command_type == "automation.resume":
|
|
97
106
|
if archived or terminal:
|
{abstractruntime-0.8.1 → abstractruntime-0.8.3}/src/abstractruntime/automations/controller.py
RENAMED
|
@@ -320,7 +320,17 @@ def _never_granted(name: str) -> bool:
|
|
|
320
320
|
`send` network reach (`agora_post_message`, `agora_send_dm`, which have no core row)."""
|
|
321
321
|
from ..integrations.abstractcore.tool_effects import sends_messages
|
|
322
322
|
|
|
323
|
-
return _grant_excludes(name) or sends_messages(name)
|
|
323
|
+
return _grant_excludes(name) or sends_messages(name) or _is_mcp_tool(name)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
# Tools of registered MCP servers (`mcp::<server>::<tool>`, AbstractCore's naming): external
|
|
327
|
+
# programs whose effects no fact table here describes. A run that reads text written by other
|
|
328
|
+
# people is never offered one and never granted one, named or not.
|
|
329
|
+
_MCP_TOOL_PREFIX = "mcp::"
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _is_mcp_tool(name: Any) -> bool:
|
|
333
|
+
return str(name or "").strip().startswith(_MCP_TOOL_PREFIX)
|
|
324
334
|
|
|
325
335
|
|
|
326
336
|
# `_runtime.untrusted_input = True`: the run reads text written by other people (an inbound
|
|
@@ -368,12 +378,13 @@ def grant_tool_approval(
|
|
|
368
378
|
beyond configured services, no code or command execution, no messaging, no
|
|
369
379
|
writes outside the run's workspace, no delegation). Every other tool
|
|
370
380
|
(`fetch_url`, `skim_url`, `web_search`, `execute_command`, `shell_exec`,
|
|
371
|
-
`execute_python`, `delegate_agent`, `channel_fs_write
|
|
381
|
+
`execute_python`, `delegate_agent`, `channel_fs_write`...) is
|
|
372
382
|
granted only when the user NAMED it individually in the definition
|
|
373
383
|
(`policy.untrusted_input_tools`, passed as `named_tools`), and only within
|
|
374
384
|
the target's tool ceiling. Message-sending tools (`send_email`,
|
|
375
385
|
`reply_email`, `agora_post_message`, `agora_send_dm`, ...) are never
|
|
376
|
-
granted, named or not.
|
|
386
|
+
granted, named or not. MCP tools (`mcp::<server>::<tool>`) leave the run's tool lists
|
|
387
|
+
and are never granted. A withheld call asks a person. Schedule and manual
|
|
377
388
|
automations keep the full grant (decision recorded in 0992).
|
|
378
389
|
|
|
379
390
|
Untrusted input under `approval="ask"` (framework backlog 0992 re-gate): the
|
|
@@ -397,6 +408,15 @@ def grant_tool_approval(
|
|
|
397
408
|
if not untrusted_input:
|
|
398
409
|
return
|
|
399
410
|
replaced_target_policy = True
|
|
411
|
+
mcp_withheld: list = []
|
|
412
|
+
if untrusted_input:
|
|
413
|
+
# Untrusted input: every MCP tool leaves the run's tool lists (the agent's `tools` input and
|
|
414
|
+
# the `_runtime.allowed_tools` ceiling), so the model is never offered one.
|
|
415
|
+
for holder, key in ((input_data, "tools"), (runtime_ns, "allowed_tools")):
|
|
416
|
+
raw = holder.get(key)
|
|
417
|
+
if isinstance(raw, list) and any(_is_mcp_tool(t) for t in raw):
|
|
418
|
+
mcp_withheld += [str(t).strip() for t in raw if _is_mcp_tool(t)]
|
|
419
|
+
holder[key] = [t for t in raw if not _is_mcp_tool(t)]
|
|
400
420
|
allowed = runtime_ns.get("allowed_tools")
|
|
401
421
|
names = allowed if isinstance(allowed, list) else list(TOOL_EFFECT_CLASSES)
|
|
402
422
|
candidates = sorted({n.strip() for n in names if isinstance(n, str) and n.strip()})
|
|
@@ -413,6 +433,7 @@ def grant_tool_approval(
|
|
|
413
433
|
else:
|
|
414
434
|
withheld = [n for n in candidates if _grant_excludes(n)]
|
|
415
435
|
tools = [n for n in candidates if n not in withheld]
|
|
436
|
+
withheld = withheld + sorted(set(mcp_withheld) - set(withheld))
|
|
416
437
|
policy: Dict[str, Any] = {"auto_approve_tools": tools, "withheld_tools": withheld, "source": AUTOMATION_GRANT_SOURCE}
|
|
417
438
|
if untrusted_input:
|
|
418
439
|
policy.update(
|
|
@@ -856,7 +877,10 @@ def record_outcome(turn: Turn) -> str:
|
|
|
856
877
|
return "next"
|
|
857
878
|
retry = pending.get("retry") or {"max_attempts": 1}
|
|
858
879
|
attempt = int(pending["attempt"])
|
|
859
|
-
|
|
880
|
+
# Paused: a SCHEDULED occurrence gets no further attempt (N3); a manual one (run_now,
|
|
881
|
+
# allowed while paused, `command_id` set) keeps its retries.
|
|
882
|
+
retry_blocked = bool(state.get("paused")) and pending.get("command_id") is None
|
|
883
|
+
if attempt < int(retry["max_attempts"]) and not retry_blocked:
|
|
860
884
|
retry_at = add_delay(turn.now, backoff_delay({"retry": retry}, attempt))
|
|
861
885
|
turn.decide(
|
|
862
886
|
"automation.retry_scheduled",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""AbstractCore's MCP clients, reached through AbstractRuntime (the gateway's import boundary).
|
|
2
|
+
|
|
3
|
+
The gateway may not import `abstractcore` directly (tests/test_gateway_import_boundary.py). Everything
|
|
4
|
+
it needs to test a registered MCP server and to call that server's tools from a run lives here:
|
|
5
|
+
|
|
6
|
+
- `open_mcp_client`: a connected-on-demand client for one server (stdio or Streamable HTTP). A stdio
|
|
7
|
+
server starts with exactly the environment given (`inherit_env=False`), so no gateway secret leaks
|
|
8
|
+
into a third-party process.
|
|
9
|
+
- `mcp_tool_spec`: one server tool as the spec agents see, named `mcp::<server>::<tool>`.
|
|
10
|
+
- `call_mcp_tool`: one `tools/call`, mapped to the runtime's tool result convention
|
|
11
|
+
`(success, output, error)` (the same mapping `McpToolExecutor` uses).
|
|
12
|
+
- the client error classes, for callers that turn failures into sentences.
|
|
13
|
+
|
|
14
|
+
Requires the AbstractCore MCP clients with `initialize()` and `inherit_env` (abstractcore round 3).
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any, Dict, Mapping, Optional, Sequence, Tuple
|
|
19
|
+
|
|
20
|
+
from abstractcore.mcp import ( # noqa: F401 - re-exported names
|
|
21
|
+
MCP_TOOL_PREFIX,
|
|
22
|
+
McpClient,
|
|
23
|
+
McpServerInfo,
|
|
24
|
+
McpStdioClient,
|
|
25
|
+
mcp_tool_to_abstractcore_tool_spec,
|
|
26
|
+
namespaced_tool_name,
|
|
27
|
+
parse_namespaced_tool_name,
|
|
28
|
+
)
|
|
29
|
+
from abstractcore.mcp.client import McpError, McpHttpError, McpProtocolError, McpRpcError # noqa: F401
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_mcp_tool_name(name: Any) -> bool:
|
|
33
|
+
"""True for a namespaced MCP tool name (`mcp::<server>::<tool>`)."""
|
|
34
|
+
return parse_namespaced_tool_name(str(name or "")) is not None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def open_mcp_client(
|
|
38
|
+
*,
|
|
39
|
+
transport: str,
|
|
40
|
+
command: str = "",
|
|
41
|
+
args: Sequence[str] = (),
|
|
42
|
+
cwd: Optional[str] = None,
|
|
43
|
+
env: Optional[Mapping[str, str]] = None,
|
|
44
|
+
url: str = "",
|
|
45
|
+
headers: Optional[Mapping[str, str]] = None,
|
|
46
|
+
timeout_s: Optional[float] = 30.0,
|
|
47
|
+
client_name: str = "abstractgateway",
|
|
48
|
+
) -> Any:
|
|
49
|
+
"""A client for one MCP server. stdio starts the process now (raises FileNotFoundError and
|
|
50
|
+
friends when it cannot start); http connects on the first request. Call `initialize()` first."""
|
|
51
|
+
if transport == "stdio":
|
|
52
|
+
if not str(command or "").strip():
|
|
53
|
+
raise ValueError("a stdio MCP server needs a command")
|
|
54
|
+
return McpStdioClient(
|
|
55
|
+
command=[str(command)] + [str(a) for a in args],
|
|
56
|
+
cwd=cwd or None,
|
|
57
|
+
env=dict(env or {}),
|
|
58
|
+
inherit_env=False,
|
|
59
|
+
timeout_s=timeout_s,
|
|
60
|
+
client_name=client_name,
|
|
61
|
+
)
|
|
62
|
+
if transport == "http":
|
|
63
|
+
if not str(url or "").strip():
|
|
64
|
+
raise ValueError("an http MCP server needs a URL")
|
|
65
|
+
return McpClient(url=str(url), headers=dict(headers or {}), timeout_s=timeout_s, client_name=client_name)
|
|
66
|
+
raise ValueError(f"unknown MCP transport {transport!r} (stdio or http)")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def close_mcp_client(client: Any) -> None:
|
|
70
|
+
"""Close the client; a stdio server still running afterwards is killed."""
|
|
71
|
+
try:
|
|
72
|
+
client.close()
|
|
73
|
+
except Exception: # noqa: BLE001
|
|
74
|
+
pass
|
|
75
|
+
proc = getattr(client, "_proc", None)
|
|
76
|
+
if proc is not None and proc.poll() is None:
|
|
77
|
+
try:
|
|
78
|
+
proc.kill()
|
|
79
|
+
proc.wait(timeout=2)
|
|
80
|
+
except Exception: # noqa: BLE001
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def mcp_tool_spec(*, server_id: str, tool: Dict[str, Any], transport: str) -> Dict[str, Any]:
|
|
85
|
+
"""The agent-facing spec of one MCP tool ({name: mcp::<server>::<tool>, description, parameters,
|
|
86
|
+
tags, origin}). `tool` is a tools/list entry ({name, description, inputSchema}). The origin carries
|
|
87
|
+
the server id and transport only — never a URL, header or command."""
|
|
88
|
+
server = McpServerInfo(server_id=server_id, url=f"{transport}://{server_id}", transport=transport)
|
|
89
|
+
spec = mcp_tool_to_abstractcore_tool_spec(tool, server=server)
|
|
90
|
+
origin = dict(spec.get("origin") or {})
|
|
91
|
+
origin.pop("url", None)
|
|
92
|
+
spec["origin"] = origin
|
|
93
|
+
return spec
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def call_mcp_tool(client: Any, *, tool_name: str, arguments: Optional[Dict[str, Any]] = None) -> Tuple[bool, Any, Optional[str]]:
|
|
97
|
+
"""One tools/call → (success, output, error). Raises the client's errors (the caller words them)."""
|
|
98
|
+
from .tool_executor import _mcp_result_to_error, _mcp_result_to_output
|
|
99
|
+
|
|
100
|
+
result = client.call_tool(name=tool_name, arguments=dict(arguments or {}))
|
|
101
|
+
err = _mcp_result_to_error(result)
|
|
102
|
+
if err is not None:
|
|
103
|
+
return False, None, err
|
|
104
|
+
return True, _mcp_result_to_output(result), None
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
__all__ = [
|
|
108
|
+
"MCP_TOOL_PREFIX",
|
|
109
|
+
"McpError",
|
|
110
|
+
"McpHttpError",
|
|
111
|
+
"McpProtocolError",
|
|
112
|
+
"McpRpcError",
|
|
113
|
+
"call_mcp_tool",
|
|
114
|
+
"close_mcp_client",
|
|
115
|
+
"is_mcp_tool_name",
|
|
116
|
+
"mcp_tool_spec",
|
|
117
|
+
"namespaced_tool_name",
|
|
118
|
+
"open_mcp_client",
|
|
119
|
+
"parse_namespaced_tool_name",
|
|
120
|
+
]
|
|
@@ -234,6 +234,72 @@ def test_stop_current_during_backoff_cancels_the_retry(env):
|
|
|
234
234
|
assert [d["status"] for d in done] == ["cancelled"]
|
|
235
235
|
|
|
236
236
|
|
|
237
|
+
@pytest.mark.parametrize("env", STORES, indirect=True)
|
|
238
|
+
def test_pause_during_backoff_cancels_the_retry(env):
|
|
239
|
+
"""N3: a pause lands while the occurrence only waits for its retry: no attempt 2."""
|
|
240
|
+
runtime, clock = env
|
|
241
|
+
aid = create(runtime, clock, workflow_id="flaky", input_data={"prompt": "p", "fail_until": 99}, trigger=HOURLY)
|
|
242
|
+
drive(runtime, aid)
|
|
243
|
+
assert automation_state(runtime, aid)["pending_occurrence"]["phase"] == "backoff"
|
|
244
|
+
clock.set("2026-01-01T00:00:05+00:00")
|
|
245
|
+
assert cmd(runtime, aid, "p", "pause", "2026-01-01T00:00:05+00:00")["status"] == "applied"
|
|
246
|
+
drive(runtime, aid)
|
|
247
|
+
at(runtime, clock, aid, "2026-01-01T00:00:31+00:00") # past the retry time
|
|
248
|
+
assert len(children(runtime, aid)) == 1 # attempt 2 never started
|
|
249
|
+
done = [r["payload"] for r in automation_records(runtime.ledger_store, aid, "automation.completed")]
|
|
250
|
+
assert [(d["status"], d["attention"]) for d in done] == [("cancelled", None)]
|
|
251
|
+
st = automation_state(runtime, aid)
|
|
252
|
+
assert st["paused"] is True and st["pending_occurrence"] is None
|
|
253
|
+
assert get_automation(runtime.run_store, aid)["status"] == "paused"
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@pytest.mark.parametrize("env", STORES, indirect=True)
|
|
257
|
+
def test_an_attempt_failing_while_paused_is_not_retried(env):
|
|
258
|
+
"""N3: the attempt running when the pause lands finishes; its failure schedules no retry."""
|
|
259
|
+
from abstractruntime.automations.bundle import controller_workflow_spec
|
|
260
|
+
|
|
261
|
+
runtime, clock = env
|
|
262
|
+
aid = create(runtime, clock, workflow_id="ask", trigger=HOURLY)
|
|
263
|
+
drive(runtime, aid)
|
|
264
|
+
child = children(runtime, aid)[0]
|
|
265
|
+
assert child.status == RunStatus.WAITING
|
|
266
|
+
assert cmd(runtime, aid, "p", "pause", "2026-01-01T00:01:00+00:00")["status"] == "applied"
|
|
267
|
+
assert runtime.get_state(child.run_id).status == RunStatus.WAITING # a running attempt is not stopped
|
|
268
|
+
failed = runtime.run_store.load(child.run_id)
|
|
269
|
+
failed.status = RunStatus.FAILED
|
|
270
|
+
failed.error = "boom while paused"
|
|
271
|
+
failed.waiting = None
|
|
272
|
+
runtime.run_store.save(failed)
|
|
273
|
+
ctl = runtime.get_state(aid)
|
|
274
|
+
runtime.resume(workflow=controller_workflow_spec(), run_id=aid, wait_key=ctl.waiting.wait_key,
|
|
275
|
+
payload={"sub_run_id": child.run_id, "output": {"success": False, "error": "boom while paused"}}, max_steps=0)
|
|
276
|
+
drive(runtime, aid)
|
|
277
|
+
at(runtime, clock, aid, "2026-01-01T00:10:00+00:00") # well past a 30 s backoff
|
|
278
|
+
assert len(children(runtime, aid)) == 1
|
|
279
|
+
assert list(automation_records(runtime.ledger_store, aid, "automation.retry_scheduled")) == []
|
|
280
|
+
done = [r["payload"] for r in automation_records(runtime.ledger_store, aid, "automation.completed")]
|
|
281
|
+
assert [(d["status"], d["attempts"]) for d in done] == [("failed", 1)]
|
|
282
|
+
assert automation_state(runtime, aid)["paused"] is True
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@pytest.mark.parametrize("env", STORES, indirect=True)
|
|
286
|
+
def test_a_manual_run_while_paused_keeps_its_retries(env):
|
|
287
|
+
runtime, clock = env
|
|
288
|
+
aid = create(runtime, clock, workflow_id="flaky", input_data={"prompt": "p", "fail_until": 2}, trigger=HOURLY)
|
|
289
|
+
drive(runtime, aid) # the 00:00 occurrence: attempt 1 fails, backoff
|
|
290
|
+
at(runtime, clock, aid, "2026-01-01T00:00:30+00:00") # attempt 2 succeeds
|
|
291
|
+
cmd(runtime, aid, "p", "pause", "2026-01-01T00:05:00+00:00")
|
|
292
|
+
drive(runtime, aid)
|
|
293
|
+
clock.set("2026-01-01T00:06:00+00:00")
|
|
294
|
+
assert cmd(runtime, aid, "run-1", "run_now", "2026-01-01T00:06:00+00:00")["status"] == "applied"
|
|
295
|
+
drive(runtime, aid)
|
|
296
|
+
pending = automation_state(runtime, aid)["pending_occurrence"]
|
|
297
|
+
assert pending["phase"] == "backoff" and pending["attempt"] == 2 and pending["command_id"] == "run-1"
|
|
298
|
+
at(runtime, clock, aid, "2026-01-01T00:06:30+00:00")
|
|
299
|
+
done = [r["payload"] for r in automation_records(runtime.ledger_store, aid, "automation.completed")]
|
|
300
|
+
assert [(d["status"], d["attempts"]) for d in done] == [("completed", 2), ("completed", 2)]
|
|
301
|
+
|
|
302
|
+
|
|
237
303
|
@pytest.mark.parametrize("env", STORES, indirect=True)
|
|
238
304
|
def test_archive_lets_the_current_occurrence_finish_then_ends(env):
|
|
239
305
|
runtime, clock = env
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""MCP tools in runs (round 3, lane mcp-runs): untrusted input never offers nor grants an MCP tool,
|
|
2
|
+
and the facade the gateway calls MCP servers through (stdio, exact env, mcp::<server>::<tool>)."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import textwrap
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from abstractruntime.automations.controller import grant_tool_approval
|
|
11
|
+
from abstractruntime.core.models import RunState, RunStatus
|
|
12
|
+
from abstractruntime.integrations.abstractcore import mcp_facade
|
|
13
|
+
from abstractruntime.integrations.abstractcore.effect_handlers import _execute_with_run_policy
|
|
14
|
+
from abstractruntime.integrations.abstractcore.tool_executor import (
|
|
15
|
+
ApprovalToolExecutor,
|
|
16
|
+
MappingToolExecutor,
|
|
17
|
+
ToolApprovalPolicy,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
MCP = "mcp::fake::echo"
|
|
21
|
+
EXECUTED: list = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _executor() -> ApprovalToolExecutor:
|
|
25
|
+
def _echo(**kw):
|
|
26
|
+
EXECUTED.append(MCP)
|
|
27
|
+
return kw
|
|
28
|
+
|
|
29
|
+
def _read(**kw):
|
|
30
|
+
EXECUTED.append("read_file")
|
|
31
|
+
return "x"
|
|
32
|
+
|
|
33
|
+
return ApprovalToolExecutor(delegate=MappingToolExecutor({MCP: _echo, "read_file": _read}), policy=ToolApprovalPolicy())
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _run(runtime_ns) -> RunState:
|
|
37
|
+
return RunState(run_id="r", workflow_id="w", status=RunStatus.RUNNING, current_node="n", vars={"_runtime": runtime_ns})
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.fixture(autouse=True)
|
|
41
|
+
def _clear():
|
|
42
|
+
EXECUTED.clear()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.parametrize("approval", ["auto", "ask"])
|
|
46
|
+
def test_untrusted_occurrence_removes_every_mcp_tool_from_its_tool_lists(approval):
|
|
47
|
+
data = {"tools": ["read_file", MCP, "mcp::other::x"], "_runtime": {"allowed_tools": ["read_file", MCP]}}
|
|
48
|
+
grant_tool_approval(data, untrusted_input=True, named_tools=[MCP], approval=approval)
|
|
49
|
+
assert data["tools"] == ["read_file"]
|
|
50
|
+
assert data["_runtime"]["allowed_tools"] == ["read_file"]
|
|
51
|
+
pol = data["_runtime"]["tool_policy"]
|
|
52
|
+
assert MCP in pol["withheld_tools"] and "mcp::other::x" in pol["withheld_tools"]
|
|
53
|
+
assert MCP not in pol["auto_approve_tools"]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_trusted_occurrence_keeps_mcp_tools():
|
|
57
|
+
"""Control: a schedule/manual automation keeps them (and allow-all grants them)."""
|
|
58
|
+
data = {"tools": ["read_file", MCP], "_runtime": {"allowed_tools": ["read_file", MCP]}}
|
|
59
|
+
grant_tool_approval(data, untrusted_input=False, approval="auto")
|
|
60
|
+
assert data["tools"] == ["read_file", MCP]
|
|
61
|
+
assert MCP in data["_runtime"]["tool_policy"]["auto_approve_tools"]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_untrusted_run_never_auto_runs_an_mcp_tool_even_named():
|
|
65
|
+
pol = {"auto_approve_tools": [MCP, "read_file"], "untrusted_input": True, "approval": "auto",
|
|
66
|
+
"untrusted_input_tools": [MCP, "read_file"]}
|
|
67
|
+
out = _execute_with_run_policy(_executor(), [{"name": MCP, "arguments": {}, "call_id": "1"}], _run({"tool_policy": pol}))
|
|
68
|
+
assert out["mode"] == "approval_required" and EXECUTED == []
|
|
69
|
+
# Control: the named non-MCP tool runs.
|
|
70
|
+
out = _execute_with_run_policy(_executor(), [{"name": "read_file", "arguments": {}, "call_id": "1"}], _run({"tool_policy": pol}))
|
|
71
|
+
assert out["mode"] == "executed" and EXECUTED == ["read_file"]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_static_policy_asks_for_an_mcp_tool_and_allow_all_runs_it():
|
|
75
|
+
out = _execute_with_run_policy(_executor(), [{"name": MCP, "arguments": {}, "call_id": "1"}], _run({}))
|
|
76
|
+
assert out["mode"] == "approval_required" and EXECUTED == []
|
|
77
|
+
out = _execute_with_run_policy(_executor(), [{"name": MCP, "arguments": {}, "call_id": "1"}],
|
|
78
|
+
_run({"tool_policy": {"auto_approve_max_risk_rank": 4}}))
|
|
79
|
+
assert out["mode"] == "executed" and EXECUTED == [MCP]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
FAKE = textwrap.dedent(
|
|
83
|
+
"""
|
|
84
|
+
import json, os, sys
|
|
85
|
+
for line in sys.stdin:
|
|
86
|
+
req = json.loads(line)
|
|
87
|
+
rid, m = req.get("id"), req.get("method")
|
|
88
|
+
if rid is None:
|
|
89
|
+
continue
|
|
90
|
+
if m == "initialize":
|
|
91
|
+
res = {"protocolVersion": "2025-06-18", "capabilities": {"tools": {}}, "serverInfo": {"name": "fake", "version": "1"}}
|
|
92
|
+
elif m == "tools/call":
|
|
93
|
+
a = req["params"]["arguments"]
|
|
94
|
+
res = {"content": [{"type": "text", "text": json.dumps({"echo": a.get("text"), "secret_env": os.environ.get("GW_SECRET")})}]}
|
|
95
|
+
else:
|
|
96
|
+
res = {"tools": [{"name": "echo", "description": "Echo text.", "inputSchema": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}]}
|
|
97
|
+
sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": rid, "result": res}) + "\\n"); sys.stdout.flush()
|
|
98
|
+
"""
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_facade_calls_a_stdio_server_with_exactly_the_given_env(tmp_path, monkeypatch):
|
|
103
|
+
script = tmp_path / "fake.py"
|
|
104
|
+
script.write_text(FAKE)
|
|
105
|
+
monkeypatch.setenv("GW_SECRET", "must-not-leak")
|
|
106
|
+
client = mcp_facade.open_mcp_client(transport="stdio", command=sys.executable, args=[str(script)], cwd=str(tmp_path),
|
|
107
|
+
env={"PATH": "/usr/bin:/bin"}, timeout_s=10)
|
|
108
|
+
try:
|
|
109
|
+
client.initialize()
|
|
110
|
+
tools = client.list_tools()
|
|
111
|
+
ok, output, err = mcp_facade.call_mcp_tool(client, tool_name="echo", arguments={"text": "hi"})
|
|
112
|
+
finally:
|
|
113
|
+
mcp_facade.close_mcp_client(client)
|
|
114
|
+
assert (ok, err) == (True, None)
|
|
115
|
+
assert output == {"echo": "hi", "secret_env": None}
|
|
116
|
+
spec = mcp_facade.mcp_tool_spec(server_id="fake", tool=tools[0], transport="stdio")
|
|
117
|
+
assert spec["name"] == MCP and "text" in spec["parameters"]
|
|
118
|
+
assert "url" not in spec["origin"] and spec["origin"]["server_id"] == "fake"
|
|
119
|
+
assert mcp_facade.is_mcp_tool_name(MCP) and not mcp_facade.is_mcp_tool_name("read_file")
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
Email automations never trigger themselves, speech and images work without a buildable text model,
|
|
2
|
-
and a chat's mail to its owner runs without asking. Requires AbstractCore 2.20.2.
|
|
3
|
-
|
|
4
|
-
### Added
|
|
5
|
-
- Mail sent by an automation run (controller, occurrence, any run it starts, the send-email action)
|
|
6
|
-
is automatic mail: the run's `EmailContext` gets `automation_marker =
|
|
7
|
-
"automation:<automation id>/run:<run id>"`, so every send carries `Auto-Submitted` and
|
|
8
|
-
`X-AbstractFramework-Automation`. `automation_marker_for(vars, run_id)` is exported from
|
|
9
|
-
`abstractruntime.email.binding`. Chats and discussions send ordinary mail.
|
|
10
|
-
- `email.received@1` config `auto_submitted`: `"skip"` (default) never admits a message whose
|
|
11
|
-
`Auto-Submitted` header is present and not `no`; `"admit"` lets it reach the filters. Stored
|
|
12
|
-
configs without the key behave like `"skip"`.
|
|
13
|
-
- `EmailInboxFeeder(..., is_own_sent=callable)` and `PollReport.own_automatic`: the account's own
|
|
14
|
-
automatic mail (the framework marker from its own address, or a Message-ID the host recorded as
|
|
15
|
-
sent) never enters the event inbox.
|
|
16
|
-
- `abstractruntime.integrations.abstractcore.run_facade.inline_run_active(run_id)`: true while the
|
|
17
|
-
run facade executes a child run in this process; host runners skip such runs.
|
|
18
|
-
- `ToolApprovalPolicy.default_require_approval_tools`: the names on the require list only because
|
|
19
|
-
no list was given (the default caution list).
|
|
20
|
-
|
|
21
|
-
### Changed
|
|
22
|
-
- The pooled local client runs media-only requests (image, video, voice, music, transcription, no
|
|
23
|
-
tools) and streaming TTS on AbstractCore's capability host instead of building the default text
|
|
24
|
-
client: text-to-speech no longer fails when the text default cannot be built (for example an
|
|
25
|
-
MLX route on an install without MLX), and no text model is loaded for a media request.
|
|
26
|
-
- Without a per-run tool policy, the `send_email_recipient@v2` refiner now also lowers a name that
|
|
27
|
-
is on the executor's default caution list (`send_email` under `ToolApprovalPolicy()`): a chat
|
|
28
|
-
run's send to its owner's own address runs without an approval wait. An explicitly passed
|
|
29
|
-
require list and a per-run policy's still win; email-triggered runs under `approval: "ask"` are
|
|
30
|
-
unchanged.
|
|
31
|
-
|
|
32
|
-
### Dependencies
|
|
33
|
-
- `abstractcore>=2.20.2` (also `[apple]` and `[gpu]`).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|