phronomy 0.26.0 → 0.28.0
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.
- checksums.yaml +4 -4
- data/.mutant.yml +9 -9
- data/CHANGELOG.md +92 -0
- data/CONTRIBUTING.md +8 -8
- data/README.md +13 -3
- data/VERIFY.sh +27 -27
- data/benchmark/bench_agent_invoke.rb +26 -47
- data/benchmark/bench_context_assembler.rb +17 -15
- data/benchmark/bench_regression.rb +1 -1
- data/benchmark/bench_tool_schema.rb +1 -1
- data/docs/architecture/agent-chat-and-state-ownership.md +153 -0
- data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
- data/docs/architecture/agent-context.md +4 -2
- data/docs/architecture/agent-transition-ownership.md +13 -0
- data/docs/architecture/backend-groups.md +152 -0
- data/docs/architecture/before-llm-input.md +9 -3
- data/docs/architecture/context-management.md +31 -1
- data/docs/architecture/context-preparation-steps.md +90 -0
- data/docs/architecture/entry-action-and-team-wording.md +72 -0
- data/docs/architecture/execution-abstraction-review.md +88 -0
- data/docs/architecture/execution-boundaries.md +28 -0
- data/docs/architecture/execution-metadata-and-values.md +86 -0
- data/docs/architecture/generator-verifier-ownership.md +111 -0
- data/docs/architecture/multi-agent-handoff.md +11 -4
- data/docs/architecture/persistence-refactoring-plan.md +50 -0
- data/docs/architecture/persistence.md +45 -4
- data/docs/architecture/r8-unit1.md +104 -0
- data/docs/architecture/r8-unit10.md +72 -0
- data/docs/architecture/r8-unit11.md +71 -0
- data/docs/architecture/r8-unit12.md +67 -0
- data/docs/architecture/r8-unit13.md +61 -0
- data/docs/architecture/r8-unit14.md +72 -0
- data/docs/architecture/r8-unit15.md +65 -0
- data/docs/architecture/r8-unit16.md +54 -0
- data/docs/architecture/r8-unit17.md +73 -0
- data/docs/architecture/r8-unit18.md +92 -0
- data/docs/architecture/r8-unit19.md +61 -0
- data/docs/architecture/r8-unit2.md +55 -0
- data/docs/architecture/r8-unit20.md +51 -0
- data/docs/architecture/r8-unit21.md +79 -0
- data/docs/architecture/r8-unit22.md +74 -0
- data/docs/architecture/r8-unit23.md +81 -0
- data/docs/architecture/r8-unit3.md +130 -0
- data/docs/architecture/r8-unit4.md +79 -0
- data/docs/architecture/r8-unit5.md +115 -0
- data/docs/architecture/r8-unit6.md +71 -0
- data/docs/architecture/r8-unit7.md +70 -0
- data/docs/architecture/r8-unit8.md +78 -0
- data/docs/architecture/r8-unit9.md +73 -0
- data/docs/architecture/refactoring-closure.md +343 -0
- data/docs/architecture/remaining-refactoring-plan.md +390 -0
- data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
- data/docs/architecture/storage-execution-boundaries.md +54 -0
- data/docs/architecture/tool-schema-recording-gap.md +56 -0
- data/docs/architecture/tracing.md +2 -2
- data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
- data/docs/architecture.md +222 -0
- data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
- data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
- data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
- data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
- data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
- data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
- data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +7 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +7 -0
- data/docs/decisions/032-storage-backend-composition.md +85 -0
- data/docs/decisions/033-domain-persistence-ownership.md +79 -0
- data/docs/decisions/034-handoff-runner-coordination-ownership.md +78 -0
- data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
- data/docs/decisions/036-context-contract-ownership.md +86 -0
- data/docs/decisions/037-common-definition-ownership.md +62 -0
- data/docs/decisions/038-responsibility-based-source-layout.md +145 -0
- data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +82 -0
- data/docs/decisions/040-configuration-default-composition.md +105 -0
- data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
- data/docs/decisions/042-feature-owned-execution-state.md +106 -0
- data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
- data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
- data/docs/decisions/045-worker-input-restriction-ownership.md +104 -0
- data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
- data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
- data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
- data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
- data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
- data/docs/decisions/051-execution-outcome-worker-ownership.md +153 -0
- data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
- data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
- data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
- data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
- data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
- data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
- data/docs/decisions/058-neutral-storage-primitives.md +83 -0
- data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
- data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
- data/docs/decisions/061-persistence-failure-contracts.md +89 -0
- data/docs/decisions/062-content-store-service.md +52 -0
- data/docs/decisions/063-execution-contracts-and-services.md +88 -0
- data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
- data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
- data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
- data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
- data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
- data/docs/decisions/README.md +52 -6
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
- data/docs/execution-boundaries-preview.md +45 -0
- data/docs/features.md +16 -5
- data/docs/getting-started.md +11 -8
- data/docs/migrations/0.15.md +5 -0
- data/docs/migrations/0.22.md +2 -2
- data/docs/migrations/durable-semantic-coordination-v2.md +8 -0
- data/docs/migrations/handoff-runner-multi-agent.md +37 -0
- data/docs/migrations/neutral-storage-spi.md +43 -0
- data/docs/migrations/parallel-tool-chat-removal.md +49 -0
- data/docs/migrations/persistence-failure-contracts.md +67 -0
- data/docs/migrations/r8-unit10.md +36 -0
- data/docs/migrations/r8-unit11.md +33 -0
- data/docs/migrations/r8-unit12.md +31 -0
- data/docs/migrations/r8-unit13.md +36 -0
- data/docs/migrations/r8-unit14.md +31 -0
- data/docs/migrations/r8-unit15.md +31 -0
- data/docs/migrations/r8-unit16.md +26 -0
- data/docs/migrations/r8-unit17.md +28 -0
- data/docs/migrations/r8-unit18.md +29 -0
- data/docs/migrations/r8-unit19.md +28 -0
- data/docs/migrations/r8-unit20.md +24 -0
- data/docs/migrations/r8-unit21.md +28 -0
- data/docs/migrations/r8-unit22.md +29 -0
- data/docs/migrations/r8-unit23.md +20 -0
- data/docs/migrations/r8-unit4.md +67 -0
- data/docs/migrations/r8-unit5.md +75 -0
- data/docs/migrations/r8-unit6.md +109 -0
- data/docs/migrations/r8-unit7.md +31 -0
- data/docs/migrations/r8-unit8.md +33 -0
- data/docs/migrations/r8-unit9.md +28 -0
- data/docs/migrations/shared-state-multi-agent.md +44 -0
- data/docs/migrations/storage-async-client.md +103 -0
- data/docs/migrations/storage-backend-composition.md +117 -0
- data/docs/migrations/storage-transaction-boundaries.md +74 -0
- data/docs/migrations/vector-async-clients.md +110 -0
- data/docs/persistence-backends.md +190 -215
- data/docs/runtime-and-concurrency.md +142 -32
- data/lib/phronomy/agent/admission.rb +78 -0
- data/lib/phronomy/{agent_already_exists_error.rb → agent/agent_already_exists_error.rb} +2 -0
- data/lib/phronomy/{agent_busy_error.rb → agent/agent_busy_error.rb} +2 -0
- data/lib/phronomy/{agent_purged_error.rb → agent/agent_purged_error.rb} +2 -0
- data/lib/phronomy/agent/api/agent.rb +17 -0
- data/lib/phronomy/{execution_rehydration_required_error.rb → agent/api/execution_rehydration_required_error.rb} +2 -0
- data/lib/phronomy/agent/async_event_api.rb +38 -33
- data/lib/phronomy/agent/base.rb +106 -294
- data/lib/phronomy/agent/before_llm_input.rb +64 -0
- data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
- data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
- data/lib/phronomy/agent/context_importer.rb +2 -2
- data/lib/phronomy/agent/{context_assembler.rb → context_preparation.rb} +157 -288
- data/lib/phronomy/agent/control_request.rb +21 -0
- data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
- data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +32 -63
- data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +195 -0
- data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +43 -23
- data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +8 -5
- data/lib/phronomy/agent/execution/execution_coordinator.rb +1744 -0
- data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
- data/lib/phronomy/agent/execution/execution_metadata.rb +54 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +288 -0
- data/lib/phronomy/agent/execution/execution_registry.rb +463 -0
- data/lib/phronomy/agent/execution/execution_session_runner.rb +113 -0
- data/lib/phronomy/agent/execution/initial_preparation.rb +323 -0
- data/lib/phronomy/agent/execution/invocation_actions.rb +368 -0
- data/lib/phronomy/agent/execution/invocation_transitions.rb +124 -0
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
- data/lib/phronomy/agent/execution_change.rb +161 -0
- data/lib/phronomy/agent/execution_environment.rb +36 -0
- data/lib/phronomy/agent/execution_extension_state.rb +21 -0
- data/lib/phronomy/agent/execution_observation.rb +35 -0
- data/lib/phronomy/agent/filterable.rb +182 -0
- data/lib/phronomy/agent/{handoff_context.rb → handoff/transfer_context.rb} +6 -6
- data/lib/phronomy/agent/{handoff_projection.rb → handoff/transfer_projection.rb} +14 -33
- data/lib/phronomy/agent/handoff_error.rb +7 -0
- data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
- data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
- data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
- data/lib/phronomy/agent/knowledge_item.rb +13 -0
- data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
- data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
- data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -15
- data/lib/phronomy/agent/persistence/agent_repository.rb +69 -0
- data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
- data/lib/phronomy/agent/persistence/codec.rb +338 -0
- data/lib/phronomy/agent/persistence/execution_repository.rb +124 -0
- data/lib/phronomy/agent/persistence/journal_repository.rb +63 -0
- data/lib/phronomy/agent/persistence/records.rb +33 -0
- data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
- data/lib/phronomy/agent/persistence/storage_schema.rb +29 -0
- data/lib/phronomy/agent/persistence/watermark.rb +29 -0
- data/lib/phronomy/agent/recovery/invocation_restorer.rb +124 -0
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +28 -51
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +50 -55
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +38 -43
- data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +26 -23
- data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
- data/lib/phronomy/agent/recovery/recovery_support.rb +224 -0
- data/lib/phronomy/agent/reserved_execution.rb +16 -0
- data/lib/phronomy/agent/retention.rb +17 -0
- data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
- data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
- data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
- data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
- data/lib/phronomy/agent/{ruby_llm_materializer.rb → runtime_input.rb} +19 -39
- data/lib/phronomy/agent/saved_context_reader.rb +55 -0
- data/lib/phronomy/agent/settings.rb +47 -0
- data/lib/phronomy/agent/state_writer.rb +166 -0
- data/lib/phronomy/agent/store.rb +253 -0
- data/lib/phronomy/{stream_callback_error.rb → agent/stream_callback_error.rb} +2 -0
- data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
- data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
- data/lib/phronomy/agent/tool_execution/tool_binding.rb +30 -0
- data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +114 -248
- data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
- data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
- data/lib/phronomy/common/configuration_error.rb +7 -0
- data/lib/phronomy/common/error.rb +5 -0
- data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
- data/lib/phronomy/common/values/serializable.rb +32 -0
- data/lib/phronomy/configuration/runtime_settings.rb +49 -0
- data/lib/phronomy/content_store/storage_schema.rb +12 -0
- data/lib/phronomy/content_store/stored_contents.rb +44 -0
- data/lib/phronomy/context/assembly.rb +202 -0
- data/lib/phronomy/{context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +5 -1
- data/lib/phronomy/context/candidate.rb +51 -0
- data/lib/phronomy/context/constraint.rb +47 -0
- data/lib/phronomy/{agent → context}/context_plan.rb +2 -2
- data/lib/phronomy/{agent → context}/context_plan_validator.rb +3 -3
- data/lib/phronomy/{agent → context}/context_policy.rb +1 -1
- data/lib/phronomy/{agent → context}/context_policy_input.rb +7 -7
- data/lib/phronomy/{agent → context}/context_policy_input_builder.rb +1 -1
- data/lib/phronomy/context/default_policy.rb +140 -0
- data/lib/phronomy/context/final_budget_validator.rb +33 -0
- data/lib/phronomy/{agent → context}/llm_input_build_context.rb +2 -2
- data/lib/phronomy/{agent → context}/llm_input_manifest.rb +21 -21
- data/lib/phronomy/{agent → context}/llm_input_patch.rb +3 -3
- data/lib/phronomy/context/manifest_error.rb +10 -0
- data/lib/phronomy/context/prompt_template.rb +98 -0
- data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
- data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
- data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
- data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
- data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
- data/lib/phronomy/embeddings/async/async_client.rb +44 -0
- data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +48 -0
- data/lib/phronomy/embeddings/base.rb +43 -0
- data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
- data/lib/phronomy/embeddings/transport_error.rb +11 -0
- data/lib/phronomy/engine/concurrency/offload_pool.rb +39 -20
- data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
- data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +1 -1
- data/lib/phronomy/engine/event_loop.rb +164 -630
- data/lib/phronomy/engine/execution_binding.rb +23 -0
- data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
- data/lib/phronomy/engine/fsm_protocol.rb +9 -0
- data/lib/phronomy/engine/fsm_session.rb +37 -30
- data/lib/phronomy/engine/metrics.rb +28 -0
- data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
- data/lib/phronomy/engine/runtime.rb +104 -95
- data/lib/phronomy/engine/terminal_decision.rb +7 -0
- data/lib/phronomy/execution/async_operation.rb +41 -0
- data/lib/phronomy/execution/backpressure_error.rb +7 -0
- data/lib/phronomy/{blocking.rb → execution/blocking.rb} +2 -2
- data/lib/phronomy/execution/cancellation_error.rb +7 -0
- data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +5 -1
- data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
- data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
- data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
- data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
- data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
- data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
- data/lib/phronomy/execution/concurrency/worker_input_restricted.rb +14 -0
- data/lib/phronomy/execution/event_loop_reentrancy_error.rb +8 -0
- data/lib/phronomy/{execution.rb → execution/execution.rb} +57 -30
- data/lib/phronomy/{execution_cancellation_error.rb → execution/execution_cancellation_error.rb} +2 -0
- data/lib/phronomy/execution/execution_receiver.rb +78 -0
- data/lib/phronomy/execution/execution_scope_state.rb +35 -0
- data/lib/phronomy/{execution_timeout_error.rb → execution/execution_timeout_error.rb} +2 -0
- data/lib/phronomy/{invalid_async_entry_action_error.rb → execution/invalid_async_entry_action_error.rb} +2 -0
- data/lib/phronomy/{invalid_async_transition_action_error.rb → execution/invalid_async_transition_action_error.rb} +2 -0
- data/lib/phronomy/{invalid_async_workflow_action_error.rb → execution/invalid_async_workflow_action_error.rb} +2 -0
- data/lib/phronomy/{invocation_context.rb → execution/invocation_context.rb} +0 -15
- data/lib/phronomy/execution/invocation_controls.rb +73 -0
- data/lib/phronomy/execution/pool_shutdown_error.rb +7 -0
- data/lib/phronomy/execution/recursion_limit_error.rb +7 -0
- data/lib/phronomy/execution/runnable.rb +24 -0
- data/lib/phronomy/execution/runtime_shutdown_error.rb +7 -0
- data/lib/phronomy/execution/runtime_shutdown_reentrancy_error.rb +7 -0
- data/lib/phronomy/execution/scheduler_reentrancy_error.rb +9 -0
- data/lib/phronomy/{engine → execution}/task_result.rb +7 -3
- data/lib/phronomy/execution/timeout_error.rb +7 -0
- data/lib/phronomy/execution/wait_policy.rb +24 -0
- data/lib/phronomy/filter/filter_block_error.rb +14 -0
- data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
- data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
- data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
- data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
- data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
- data/lib/phronomy/generation/generator_verifier.rb +118 -0
- data/lib/phronomy/generation/low_confidence_error.rb +14 -0
- data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
- data/lib/phronomy/llm_adapter/authentication_error.rb +9 -0
- data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
- data/lib/phronomy/llm_adapter/base.rb +49 -68
- data/lib/phronomy/llm_adapter/context_length_error.rb +9 -0
- data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
- data/lib/phronomy/llm_adapter/message.rb +62 -0
- data/lib/phronomy/llm_adapter/rate_limit_error.rb +9 -0
- data/lib/phronomy/llm_adapter/request.rb +79 -0
- data/lib/phronomy/llm_adapter/response.rb +36 -0
- data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
- data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
- data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
- data/lib/phronomy/llm_adapter.rb +3 -16
- data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
- data/lib/phronomy/multi_agent/admission_registry.rb +15 -2
- data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
- data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
- data/lib/phronomy/{agent → multi_agent}/handoff.rb +2 -2
- data/lib/phronomy/{agent → multi_agent}/handoff_capability_factory.rb +21 -2
- data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
- data/lib/phronomy/{agent → multi_agent}/handoff_policy.rb +1 -1
- data/lib/phronomy/multi_agent/handoff_runner.rb +156 -0
- data/lib/phronomy/{agent → multi_agent}/handoff_state.rb +2 -2
- data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
- data/lib/phronomy/multi_agent/persistence/codec.rb +75 -0
- data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
- data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
- data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
- data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +124 -0
- data/lib/phronomy/multi_agent/persistence/team_repository.rb +69 -0
- data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
- data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
- data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
- data/lib/phronomy/multi_agent/store.rb +156 -0
- data/lib/phronomy/multi_agent/team_coordinator.rb +87 -75
- data/lib/phronomy/multi_agent/team_execution.rb +1 -1
- data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +5 -5
- data/lib/phronomy/multi_agent/team_root.rb +1 -1
- data/lib/phronomy/output_parser/parse_error.rb +7 -0
- data/lib/phronomy/persistence/content_repository.rb +26 -0
- data/lib/phronomy/persistence/errors.rb +16 -0
- data/lib/phronomy/persistence/migration/initial_format_migration.rb +21 -21
- data/lib/phronomy/persistence/persistence.rb +23 -0
- data/lib/phronomy/persistence/save_outcome.rb +24 -0
- data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
- data/lib/phronomy/persistence/storage_boundary.rb +32 -0
- data/lib/phronomy/persistence/transaction.rb +86 -0
- data/lib/phronomy/persistence_composition/storage_schema.rb +29 -0
- data/lib/phronomy/persistence_composition/stores.rb +34 -0
- data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
- data/lib/phronomy/runtime_composition/agent_defaults.rb +11 -0
- data/lib/phronomy/runtime_composition/configuration.rb +146 -0
- data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
- data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
- data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
- data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
- data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
- data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
- data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
- data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
- data/lib/phronomy/storage/async/async_client.rb +60 -0
- data/lib/phronomy/storage/backend.rb +107 -0
- data/lib/phronomy/storage/backends/in_memory.rb +157 -0
- data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
- data/lib/phronomy/storage/blobs.rb +31 -0
- data/lib/phronomy/storage/condition.rb +25 -0
- data/lib/phronomy/storage/condition_failed_error.rb +16 -0
- data/lib/phronomy/storage/conflict_error.rb +9 -0
- data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
- data/lib/phronomy/storage/entry.rb +33 -0
- data/lib/phronomy/storage/guard_ref.rb +13 -0
- data/lib/phronomy/storage/not_found_error.rb +9 -0
- data/lib/phronomy/storage/record_codec.rb +177 -0
- data/lib/phronomy/storage/records.rb +61 -0
- data/lib/phronomy/storage/resource.rb +126 -0
- data/lib/phronomy/storage/scope.rb +25 -0
- data/lib/phronomy/storage/serialization_error.rb +9 -0
- data/lib/phronomy/storage/streams.rb +44 -0
- data/lib/phronomy/storage/transaction_error.rb +10 -0
- data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
- data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
- data/lib/phronomy/storage/validation.rb +53 -0
- data/lib/phronomy/storage/view.rb +131 -0
- data/lib/phronomy/testing/eval/metrics.rb +1 -1
- data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
- data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +54 -48
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +52 -46
- data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
- data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +124 -0
- data/lib/phronomy/testing/persistence_contract.rb +4 -0
- data/lib/phronomy/tool/authorization.rb +77 -0
- data/lib/phronomy/tool/base.rb +549 -9
- data/lib/phronomy/tool/call_request.rb +40 -0
- data/lib/phronomy/{agent/tool_definition_set.rb → tool/definition_set.rb} +16 -12
- data/lib/phronomy/tool/operation.rb +88 -0
- data/lib/phronomy/tool/schema.rb +214 -0
- data/lib/phronomy/tool/settings.rb +31 -0
- data/lib/phronomy/tool/tool_error.rb +7 -0
- data/lib/phronomy/{agent → tool}/tool_executor.rb +10 -7
- data/lib/phronomy/tools/agent.rb +22 -90
- data/lib/phronomy/tools/mcp.rb +21 -14
- data/lib/phronomy/tools/vector_search.rb +4 -4
- data/lib/phronomy/tracing/automatic.rb +11 -6
- data/lib/phronomy/tracing/base.rb +1 -1
- data/lib/phronomy/tracing/observation.rb +37 -0
- data/lib/phronomy/tracing/settings.rb +36 -0
- data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
- data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
- data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
- data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
- data/lib/phronomy/vector_store/base.rb +118 -49
- data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
- data/lib/phronomy/vector_store.rb +2 -17
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/workflow/completion.rb +11 -0
- data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +10 -8
- data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
- data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +5 -1
- data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
- data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +27 -0
- data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +186 -0
- data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +145 -115
- data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
- data/lib/phronomy/workflow/persistence/codec.rb +153 -0
- data/lib/phronomy/workflow/persistence/state_repository.rb +63 -0
- data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +38 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +156 -0
- data/lib/phronomy/workflow/runtime_binding/workflow_terminal_policy.rb +40 -0
- data/lib/phronomy.rb +97 -98
- data/scripts/api_snapshot.rb +36 -16
- data/scripts/storage_spi_snapshot.rb +36 -0
- data/sig/_private/phronomy/agent/settings.rbs +19 -0
- data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
- data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
- data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
- data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
- data/sig/_private/phronomy/tool/settings.rbs +13 -0
- data/sig/_private/phronomy/tracing/settings.rbs +15 -0
- data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
- data/sig/phronomy/agent/admission.rbs +19 -0
- data/sig/phronomy/agent/execution_contract.rbs +132 -0
- data/sig/phronomy/agent/execution_environment.rbs +20 -0
- data/sig/phronomy/agent/store.rbs +73 -0
- data/sig/phronomy/agent.rbs +14 -139
- data/sig/phronomy/common.rbs +7 -0
- data/sig/phronomy/content_store/contracts.rbs +13 -0
- data/sig/phronomy/context.rbs +152 -0
- data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
- data/sig/phronomy/embeddings/base.rbs +17 -0
- data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
- data/sig/phronomy/engine/control_bindings.rbs +11 -0
- data/sig/phronomy/engine/control_protocols.rbs +23 -0
- data/sig/phronomy/engine/execution_binding.rbs +6 -0
- data/sig/phronomy/engine/execution_receiver.rbs +15 -0
- data/sig/phronomy/engine/observability.rbs +13 -0
- data/sig/phronomy/execution/async_operation.rbs +7 -0
- data/sig/phronomy/execution/blocking.rbs +5 -0
- data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
- data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
- data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
- data/sig/phronomy/execution/control_protocols.rbs +18 -0
- data/sig/phronomy/execution/errors.rbs +7 -0
- data/sig/phronomy/execution/execution.rbs +41 -0
- data/sig/phronomy/execution/execution_receiver.rbs +40 -0
- data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
- data/sig/phronomy/execution/invocation_context.rbs +18 -0
- data/sig/phronomy/execution/invocation_controls.rbs +13 -0
- data/sig/phronomy/execution/task_result.rbs +29 -0
- data/sig/phronomy/extensions.rbs +0 -21
- data/sig/phronomy/handoff.rbs +12 -4
- data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
- data/sig/phronomy/llm_adapter/base.rbs +14 -0
- data/sig/phronomy/llm_adapter/usage.rbs +14 -0
- data/sig/phronomy/llm_adapter/values.rbs +43 -0
- data/sig/phronomy/llm_context_window.rbs +10 -0
- data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
- data/sig/phronomy/multi_agent/store.rbs +54 -0
- data/sig/phronomy/multi_agent.rbs +24 -3
- data/sig/phronomy/persistence/errors.rbs +18 -0
- data/sig/phronomy/persistence/migration.rbs +13 -0
- data/sig/phronomy/persistence/transaction.rbs +19 -0
- data/sig/phronomy/persistence.rbs +3 -185
- data/sig/phronomy/persistence_composition.rbs +19 -0
- data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
- data/sig/phronomy/storage/async/async_client.rbs +8 -0
- data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
- data/sig/phronomy/storage/contracts.rbs +160 -0
- data/sig/phronomy/tool.rbs +58 -5
- data/sig/phronomy/tracing/observation.rbs +7 -0
- data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
- data/sig/phronomy/vector_store/base.rbs +23 -0
- data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +14 -0
- data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
- data/sig/phronomy/workflow/store.rbs +8 -0
- data/sig/phronomy/workflow.rbs +1 -1
- data/sig/phronomy.rbs +0 -49
- metadata +462 -130
- data/lib/phronomy/agent/agent_invocation_session_builder.rb +0 -584
- data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
- data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
- data/lib/phronomy/agent/concerns/filterable.rb +0 -184
- data/lib/phronomy/agent/context/capability/base.rb +0 -507
- data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
- data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
- data/lib/phronomy/agent/context_policies/default.rb +0 -142
- data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
- data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
- data/lib/phronomy/agent/handoff_request.rb +0 -45
- data/lib/phronomy/agent/handoff_runner.rb +0 -178
- data/lib/phronomy/agent/phase_machine_builder.rb +0 -152
- data/lib/phronomy/agent/provider_call_outcome.rb +0 -106
- data/lib/phronomy/agent/recovery_support.rb +0 -504
- data/lib/phronomy/agent/selection/candidate.rb +0 -53
- data/lib/phronomy/agent/selection/constraint.rb +0 -49
- data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
- data/lib/phronomy/agent/tool_call_intercepted.rb +0 -29
- data/lib/phronomy/agent/tool_invocation_session_builder.rb +0 -276
- data/lib/phronomy/configuration.rb +0 -59
- data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
- data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
- data/lib/phronomy/generator_verifier.rb +0 -369
- data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
- data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
- data/lib/phronomy/metrics.rb +0 -26
- data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
- data/lib/phronomy/persistence/durable_codec.rb +0 -706
- data/lib/phronomy/persistence/in_memory.rb +0 -690
- data/lib/phronomy/persistence/repository_facades.rb +0 -535
- data/lib/phronomy/persistence.rb +0 -276
- data/lib/phronomy/recovery.rb +0 -186
- data/lib/phronomy/ruby_llm_patches.rb +0 -24
- data/lib/phronomy/runnable.rb +0 -54
- data/lib/phronomy/token_usage.rb +0 -85
- data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
- data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
- data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
- data/lib/phronomy/workflow_recovery.rb +0 -123
- data/sig/phronomy/llm_adapter.rbs +0 -11
- data/sig/phronomy/runtime.rbs +0 -76
- /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
- /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
- /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# r8 unit 3: Persistence ownership and Team/Agent operations
|
|
2
|
+
|
|
3
|
+
This is a candidate based on core `a82974a7fd2360a13af71831a0c3ddc75942fae3`
|
|
4
|
+
and examples `70b7244c9f6542062849869a7106c5a627868a80`. It implements P01 and
|
|
5
|
+
removes concrete adapter selection from the unit 2 admission framework. P04 is
|
|
6
|
+
partially implemented for Team authorization and scheduling. It is not completion
|
|
7
|
+
of the full contract architecture.
|
|
8
|
+
|
|
9
|
+
## Ownership and public application construction
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
stores = Phronomy::PersistenceComposition.in_memory
|
|
13
|
+
# Or: PersistenceComposition.build(backend: configured_storage_backend)
|
|
14
|
+
|
|
15
|
+
Phronomy.configure do |config|
|
|
16
|
+
config.agent_store = stores.agent
|
|
17
|
+
config.team_store = stores.team
|
|
18
|
+
config.workflow_store = stores.workflow
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
agent = MyAgent.create(persistence: stores.agent)
|
|
22
|
+
team = MyTeam.create(persistence: stores.team)
|
|
23
|
+
workflow = Phronomy::Workflow.define(MyContext, persistence: stores.workflow) do
|
|
24
|
+
# Workflow definition
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
agent_result = stores.agent.result(agent_execution_id)
|
|
28
|
+
team_result = stores.team.result(team_execution_id)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For an isolated Agent, `PersistenceComposition.agent(backend: optional_backend)`
|
|
32
|
+
constructs only the Agent/content components. Ordinary Agent defaults use this
|
|
33
|
+
factory. A composition result is a construction bundle, not a query or execution
|
|
34
|
+
service; pass only the relevant component to each consumer.
|
|
35
|
+
|
|
36
|
+
| Owner | Operation / responsibility |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `Persistence` | `atomic`, scope validity, participation and outer commit |
|
|
39
|
+
| `Agent::Store` | Agent result/list/presence/authorization operations, injected Agent record protocol |
|
|
40
|
+
| `MultiAgent::Store` | Team result/list operations, injected Team record protocol and Agent public operations |
|
|
41
|
+
| Workflow checkpoint port | `load`, `save`, `delete` with instance ID and expected revision |
|
|
42
|
+
| Domain `persistence/` implementations | physical resource schema, records, codecs and guards |
|
|
43
|
+
| `PersistenceComposition` | selects backend and adapters, validates schemas and binds components |
|
|
44
|
+
|
|
45
|
+
The stores are roles inside the existing domain framework, not new independent
|
|
46
|
+
contracts. Logical acceptance and state-transition decisions remain in Admission,
|
|
47
|
+
TeamCoordinator, and the owning domain operations. Record accessors on stores are
|
|
48
|
+
internal protocols for their own domain, not cross-domain application APIs.
|
|
49
|
+
Common Persistence neither knows these types nor imports composition.
|
|
50
|
+
|
|
51
|
+
## Atomic participation remains unchanged
|
|
52
|
+
|
|
53
|
+
The parent reservation is committed first. At child acceptance, the parent guard
|
|
54
|
+
is acquired before reading the current reservation, then Agent input/execution
|
|
55
|
+
and root revision are written in that same scope. The parent's domain owns its
|
|
56
|
+
reservation/cancellation/identity checks. Agent does not interpret parent schemas.
|
|
57
|
+
Only after the outer commit does Agent expose its accepted state and start work.
|
|
58
|
+
|
|
59
|
+
Domain adapters are injected at construction and receive the exact scope's view.
|
|
60
|
+
They never select another connection or commit independently. The coordinator
|
|
61
|
+
identity, same-thread lifetime, savepoint behavior, conflict classification,
|
|
62
|
+
rollback, and uncertain-commit behavior remain in force. LLM/Tool work and async
|
|
63
|
+
waiting remain outside these short transactions. Wrapping ordinary async invoke
|
|
64
|
+
in an application transaction is not a newly supported API.
|
|
65
|
+
|
|
66
|
+
## Team uses Agent authorization, not execution metadata
|
|
67
|
+
|
|
68
|
+
`Agent::Store#authorized_operations(scope, agent_id:, execution_id:,
|
|
69
|
+
invocation_id:, name:, arguments:, names:)` validates the exact requested call
|
|
70
|
+
against one persisted execution snapshot in the caller's scope. It checks the
|
|
71
|
+
Agent owner, invocation identity, authorization state, name, arguments and
|
|
72
|
+
requested operation family. It returns immutable `AuthorizedOperation` values
|
|
73
|
+
with only `invocation_id`, `name`, and `arguments`, in Provider order.
|
|
74
|
+
|
|
75
|
+
Team applies these operations and owns its durable operation-result ledger.
|
|
76
|
+
A committed replay returns that ledger result without reapplying the batch.
|
|
77
|
+
`finalize` cannot overtake earlier authorized `enqueue_task` calls. A mismatch
|
|
78
|
+
raises `Persistence::StateConflictError` before Team's changes commit.
|
|
79
|
+
`Agent::Store#exist?` reports authoritative absence; failed reads still raise.
|
|
80
|
+
|
|
81
|
+
Team scheduling now uses its own retained assignment count. The default chooses
|
|
82
|
+
the worker with the fewest assignments, breaking ties in worker order. Custom
|
|
83
|
+
schedulers receive `WorkerState#assignment_count` instead of `transcript_size`.
|
|
84
|
+
The count is derived from existing assignments, including failures; there is no
|
|
85
|
+
extra mutable counter and no Agent journal read. This deliberately changes the
|
|
86
|
+
default balancing metric. It does not estimate tokens, duration or resource load.
|
|
87
|
+
|
|
88
|
+
## Removed APIs and directories
|
|
89
|
+
|
|
90
|
+
- `Persistence.in_memory`, common `transaction`, `capabilities`, repository
|
|
91
|
+
accessors, result/list queries and Agent watermark facade methods are removed.
|
|
92
|
+
`Persistence.new(backend:)` constructs only the neutral coordinator.
|
|
93
|
+
- Domain result queries are `stores.agent.result` / `.runs` and
|
|
94
|
+
`stores.team.result` / `.runs`; Handoff observation remains on the Agent store
|
|
95
|
+
pending the ownership work below.
|
|
96
|
+
- `Configuration#persistence` is replaced by `agent_store`, `team_store`, and
|
|
97
|
+
`workflow_store`; explicit `persistence:` arguments accept the relevant port.
|
|
98
|
+
- The all-domain `PersistenceComposition::Repositories` and the fixed admission
|
|
99
|
+
adapter classes are deleted. There are no legacy API aliases.
|
|
100
|
+
- `persistence/api/` and the six-file `persistence/contract/` error subdivision
|
|
101
|
+
are removed. Shared failures are in `persistence/errors.rb`.
|
|
102
|
+
- Team/Workflow schema declarations are consolidated into their existing domain
|
|
103
|
+
`persistence/` directories; their separate `storage_contract/` directories and
|
|
104
|
+
root schema constants are removed.
|
|
105
|
+
|
|
106
|
+
Storage SPI 2 and physical SQL tables/indexes are unchanged. Existing Agent,
|
|
107
|
+
Handoff and Workflow record codecs are unchanged. New Team worker entries omit
|
|
108
|
+
`transcript_size`; older entries can still be decoded and the unused field is
|
|
109
|
+
ignored by scheduling. Assignment history remains the authority. This does not
|
|
110
|
+
add an API compatibility wrapper or change saved operation results.
|
|
111
|
+
|
|
112
|
+
## Remaining work (explicitly not claimed complete)
|
|
113
|
+
|
|
114
|
+
1. Subagent and Handoff still interpret Agent execution/routing records and
|
|
115
|
+
coordination data. Storage adapter class selection has been removed, but
|
|
116
|
+
renaming raw record access does not make it a proper public domain operation.
|
|
117
|
+
Resolve logical ownership, cancellation, responsibility transfer and restart
|
|
118
|
+
together before changing these paths; existing atomic transfer is preserved.
|
|
119
|
+
2. Orchestrator's preparation/resume integration still accesses Agent-owned
|
|
120
|
+
execution and context details. Team's new operation projection is not a
|
|
121
|
+
general solution to those ownership questions.
|
|
122
|
+
3. Domain-to-FSM connections, durable Workflow child protocols, multi-record
|
|
123
|
+
uncertain-commit evidence and the remaining semantic dependency review are
|
|
124
|
+
outside this implementation unit. Workflow FINISH translation already exists.
|
|
125
|
+
4. PostgreSQL concurrency verification for this candidate requires the matching
|
|
126
|
+
core/examples branch or local PostgreSQL setup. Unit 2 CI evidence is not
|
|
127
|
+
evidence that this candidate has passed PostgreSQL.
|
|
128
|
+
|
|
129
|
+
The source SVG and full Ruby/RBS evidence report remaining dependencies. Visual
|
|
130
|
+
suppression of shared common-value arrows does not remove graph evidence.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# r8 unit 4: Agent execution and MultiAgent responsibility
|
|
2
|
+
|
|
3
|
+
Core baseline: `3c5fddcae31cc98f8e081feae9b955cf536e5834`.
|
|
4
|
+
Examples baseline: `0370d09fb1608b9596e1803275f713b1a204af26`.
|
|
5
|
+
The foundation mapping dated 2026-09-30 and its target/concept diagrams remain the
|
|
6
|
+
refactoring goal. This change implements the C01/C04 boundary; it does not claim
|
|
7
|
+
that the whole existing implementation already matches the target DAG.
|
|
8
|
+
|
|
9
|
+
| Responsibility | Owner and current entry point |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Exact execution identity, admission and observation | Agent `ReservedExecution`, `start_reserved_async`, `resume_async`, `cancel_async`, `Store#observe_execution` |
|
|
12
|
+
| Finalized input, groups and provenance | Agent `ControlRequest`, `TransferContext`, `TransferProjection` with Context assembly |
|
|
13
|
+
| Selection policy, Source/Target mapping and routing | MultiAgent `HandoffPolicy`, capability binding, `HandoffRunner`, `HandoffParticipant` |
|
|
14
|
+
| Static subagent slot, definition, input, inherited knowledge and import progress | MultiAgent `DurableSubagentCoordinator`; immutable content snapshot |
|
|
15
|
+
| Execution/Root/journal mutation and publication authority | Agent `ExecutionChange` and `ExecutionOutcomeCommitter` |
|
|
16
|
+
| Whole-Agent retention and durable cancellation intent | Agent public operations; Agent-owned record resources |
|
|
17
|
+
| History removal and release of its own holds | MultiAgent `Store#forget_subagents`, `Store#forget_handoff` |
|
|
18
|
+
| Physical record adapters and schema | Each domain's Persistence implementation; composition assembles them |
|
|
19
|
+
| Offline old-format conversion | `PersistenceComposition::Unit4Migration`; examples SQL runner |
|
|
20
|
+
|
|
21
|
+
Agent interprets neither child states nor routing phases. MultiAgent uses public
|
|
22
|
+
Agent values and operations; it does not read AgentExecution, raw metadata,
|
|
23
|
+
journals, ContextImporter values or a private event-listener getter. Child results
|
|
24
|
+
are observed from their authoritative execution, never mirrored as mutable child
|
|
25
|
+
statuses in the parent snapshot. IDs for new slots are derived from canonical
|
|
26
|
+
parent Agent/execution/slot identity. Migration preserves existing IDs.
|
|
27
|
+
|
|
28
|
+
## Commit participant contract
|
|
29
|
+
|
|
30
|
+
A current, synchronous participant declares a `binding` key/version and implements
|
|
31
|
+
`commit`, `guard_change`, and `change_evidence`. `ExecutionChange` exposes semantic
|
|
32
|
+
inputs only. In one outer `Persistence#atomic` scope the participant:
|
|
33
|
+
|
|
34
|
+
1. Locks routing/Team guards where needed, then Agent roots in lexical ID order.
|
|
35
|
+
2. Calls `change.prepare_in(scope)` before its own writes. This captures complete
|
|
36
|
+
pre-state, including cancellation intent, under those guards.
|
|
37
|
+
3. Changes its own records and calls `change.commit_in(scope, state:, transfer_receipt:, pending:)` once.
|
|
38
|
+
4. Returns after the outer commit. Agent publishes the captured result only then.
|
|
39
|
+
|
|
40
|
+
The change is bound to the original thread, coordinator and prepared scope. It
|
|
41
|
+
checks its Agent watermark and expected execution revision. A nested savepoint
|
|
42
|
+
cannot authorize publication. Reconciliation compares Root, execution payload,
|
|
43
|
+
appended journal, extension content, cancellation intent, and participant evidence
|
|
44
|
+
in a consistent scope. Exact post-state proves commit; exact pre-state proves no
|
|
45
|
+
commit; different state or failed reads require recovery. There is no write retry.
|
|
46
|
+
An updated record at the expected revision alone is insufficient evidence.
|
|
47
|
+
|
|
48
|
+
Subagent cancellation retains unresolved active work. Known business errors may
|
|
49
|
+
follow `on_error: :skip`; unknown external outcomes cannot be skipped into success.
|
|
50
|
+
Handoff Source transfer and Target terminal stabilization join the same Agent
|
|
51
|
+
change. A suspended or recovery-required Target does not stabilize routing.
|
|
52
|
+
Current participant key/version and Target definition must match before resuming.
|
|
53
|
+
Terminal results can still be read without re-creating application wiring.
|
|
54
|
+
|
|
55
|
+
## Retention and cancellation
|
|
56
|
+
|
|
57
|
+
`agent.retentions` prevents purge independently of MultiAgent schema. C01 records
|
|
58
|
+
its parent/child or conversation holds when reserving/creating work. History
|
|
59
|
+
removal checks unfinished work, removes its references and releases only its own
|
|
60
|
+
owner key in the same transaction. Other holds remain authoritative.
|
|
61
|
+
`agent.cancellations` stores monotonic intent separately from execution revision,
|
|
62
|
+
so an external cancel does not invalidate an in-flight worker's captured revision.
|
|
63
|
+
Signal delivery follows the durable write; restored executions read that intent.
|
|
64
|
+
|
|
65
|
+
`Agent::Admission` remains the same-scope acceptance boundary. A participant never
|
|
66
|
+
starts a child inside a transaction or waits for its lifetime on a worker thread.
|
|
67
|
+
Ordinary Agent composition does not load MultiAgent routing repositories.
|
|
68
|
+
Standalone `dispatch_parallel` keeps its existing Runtime-scoped behavior.
|
|
69
|
+
|
|
70
|
+
## Remaining boundaries
|
|
71
|
+
|
|
72
|
+
`MultiAgent::AdmissionRegistry` still uses Runtime shutdown coordination. Agent,
|
|
73
|
+
Tool and Workflow execution internals still depend on existing Engine mechanisms.
|
|
74
|
+
These are later r8 work, not erased by constructor injection or diagram grouping.
|
|
75
|
+
The measured source diagram includes those edges and cycles. PostgreSQL lock
|
|
76
|
+
ordering needs its actual database gate; SQLite/InMemory results do not establish
|
|
77
|
+
PostgreSQL behavior. The application package records executed and unexecuted gates.
|
|
78
|
+
|
|
79
|
+
See [API and saved-data migration](../migrations/r8-unit4.md).
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# r8 unit 5: VectorStore and Embeddings common contracts
|
|
2
|
+
|
|
3
|
+
Core baseline: `29818f5d0577ac5287c5429d6d169ef5fd1c0225`.
|
|
4
|
+
Examples baseline: `c410fc88112ad5e4648ba2e51335023885d9373b`.
|
|
5
|
+
The contract concept and foundation target remain the design goal. This unit
|
|
6
|
+
implements C10/C11 common operation ownership and DP09/DP10 placement. It does
|
|
7
|
+
not complete the other domain Contracts or the outstanding unit 4 acceptance gates.
|
|
8
|
+
|
|
9
|
+
## Ownership and completion conditions
|
|
10
|
+
|
|
11
|
+
Contract membership follows domain semantics, not frequency of reuse. A Contract
|
|
12
|
+
defines its domain's concepts, legal inputs/results, invariants, extension points
|
|
13
|
+
and observable failure/operation rules. Its framework executes those rules.
|
|
14
|
+
Code used by several callers is not automatically a Contract; a generic utility,
|
|
15
|
+
concrete adapter helper or composition operation can have several callers too.
|
|
16
|
+
|
|
17
|
+
| Placement decision in this unit | Domain reason |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| VectorStore id/vector/metadata inputs and ordered search results | These describe the public vector storage/retrieval operation independently of a database |
|
|
20
|
+
| Embeddings text/vector inputs and results | These describe text embedding independently of the provider SDK and downstream storage |
|
|
21
|
+
| Validation, pre-operation cancellation checkpoint and InvalidResultError | These enforce the operation's observable invariants and failure rules |
|
|
22
|
+
| Float-array normalization | This realizes the declared vector representation; it does not make arbitrary serialization a Contract concern |
|
|
23
|
+
| Redis RESP2 decoding, distance-to-similarity conversion, Pgvector row/JSON decoding | These are concrete backend adaptations and remain in the corresponding backend |
|
|
24
|
+
| Document loading/splitting | These are document utilities separated from VectorStore; this move does not create a new Contract |
|
|
25
|
+
| Async submission and timeout settlement | These remain Execution responsibilities, connected through each AsyncClient |
|
|
26
|
+
|
|
27
|
+
| Responsibility | Owner | Completion evidence |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Vector operation entry, cancellation checkpoint, input/result validation, chaining | `VectorStore::Base` | A hook-only custom backend receives validated inputs; malformed inputs perform no I/O; malformed outputs fail explicitly |
|
|
30
|
+
| Search/storage algorithms, physical dimension state, database encoding | `VectorStore::{InMemory,Pgvector,RedisSearch}` | Existing algorithm and adapter tests run through inherited public operations |
|
|
31
|
+
| Text input and finite embedding result validation | `Embeddings::Base` | A hook-only provider works without SDK, Engine or VectorStore; malformed outputs are rejected |
|
|
32
|
+
| Embedding provider call and SDK exception translation | `Embeddings::RubyLLMEmbeddings` | Provider exceptions retain their cause; cancellation and application failures retain their identity |
|
|
33
|
+
| Submission, timeout, admission and completion handle | Each feature's `AsyncClient` and Execution | Existing pool, cancellation, timeout and Runtime reset tests |
|
|
34
|
+
| Document input and splitting | `Documents::Loader` / `Documents::Splitter` | Existing document tests; no VectorStore or Embeddings dependency |
|
|
35
|
+
|
|
36
|
+
Common behavior lives in the existing Base classes. There is no forwarding
|
|
37
|
+
Contract, Base-to-client factory, compatibility alias or mandatory embedding
|
|
38
|
+
provider in VectorStore. Protected `perform_*` methods are the extension SPI;
|
|
39
|
+
applications call the inherited public operations. Ruby can override any method,
|
|
40
|
+
but overriding the public template is outside the documented backend SPI.
|
|
41
|
+
|
|
42
|
+
## Defined operation behavior
|
|
43
|
+
|
|
44
|
+
`VectorStore#add` checks cancellation, a String id, Hash metadata, a vector of
|
|
45
|
+
finite real numbers and the backend's known dimension before entering the
|
|
46
|
+
storage hook. It supplies a fresh Float array and returns the store. `remove`
|
|
47
|
+
and `clear` also return the store. A search validates input and positive `k`
|
|
48
|
+
before entering its hook, including an empty Redis store. Decimal strings for
|
|
49
|
+
`k` remain supported; fractional values no longer truncate silently.
|
|
50
|
+
|
|
51
|
+
Search results must be an Array of at most `k` Hashes with String `:id`, finite
|
|
52
|
+
numeric `:score`, Hash `:metadata`, and descending score order. A count must be
|
|
53
|
+
a non-negative Integer. Violations raise `VectorStore::InvalidResultError`.
|
|
54
|
+
Backend transport failures propagate without retries. Redis count failures no
|
|
55
|
+
longer become a successful zero count. Backend-specific index creation, metadata
|
|
56
|
+
encoding and query construction remain in the backend; they are not new common
|
|
57
|
+
storage primitives. Existing dimension-zero InMemory vectors remain supported.
|
|
58
|
+
|
|
59
|
+
Backends must not invent successful values while decoding malformed external
|
|
60
|
+
responses. RedisSearch validates its RESP2 count, field pairs, document keys,
|
|
61
|
+
numeric distances and JSON object metadata before producing the public result.
|
|
62
|
+
A genuine zero-match reply is `[0]`. A missing whole reply is invalid. Redis's
|
|
63
|
+
documented null document contents after expiration/update are omitted; they do
|
|
64
|
+
not imply a corrupt response, and the total can exceed the returned page size.
|
|
65
|
+
Missing/null Redis metadata and a SQL NULL metadata column still mean empty
|
|
66
|
+
metadata. Invalid JSON text, empty JSON text, JSON scalars/arrays and invalid
|
|
67
|
+
scores raise `InvalidResultError`. Pgvector also rejects invalid row ids rather
|
|
68
|
+
than turning them into strings. JSON parse failures preserve their original cause;
|
|
69
|
+
transport/database exceptions propagate unchanged and no read is retried.
|
|
70
|
+
|
|
71
|
+
The response decoders stay private to each backend. Base does not know Redis
|
|
72
|
+
commands, RESP versions, ActiveRecord rows, JSON columns or SDK exceptions.
|
|
73
|
+
The existing RESP2 support boundary and known-dimension/index initialization
|
|
74
|
+
requirements remain; this unit does not add RESP3 support.
|
|
75
|
+
|
|
76
|
+
Protocol references: [FT.SEARCH](https://redis.io/docs/latest/commands/ft.search/)
|
|
77
|
+
and [FT.INFO](https://redis.io/docs/latest/commands/ft.info/), checked 2026-10-03.
|
|
78
|
+
|
|
79
|
+
`Embeddings#embed` checks cancellation and String input, invokes `perform_embed`
|
|
80
|
+
once, and validates a non-empty finite vector before returning Float values.
|
|
81
|
+
Malformed output raises `Embeddings::InvalidResultError`. The RubyLLM backend
|
|
82
|
+
translates `RubyLLM::Error` to `Embeddings::TransportError`, preserving `cause`.
|
|
83
|
+
This error does not imply that external work was or was not accepted. There is
|
|
84
|
+
no automatic retry and no classification of an arbitrary application exception
|
|
85
|
+
as a provider failure.
|
|
86
|
+
|
|
87
|
+
Cancellation is cooperative. The common checkpoint occurs before the backend
|
|
88
|
+
operation; a provider may inspect the same signal during its work. A successful
|
|
89
|
+
write is not changed into cancellation by a post-write check. Timeout and result
|
|
90
|
+
settlement remain Execution responsibilities; an external call may continue.
|
|
91
|
+
|
|
92
|
+
Input errors are F0 failures before X0 I/O. For a write that has crossed X0,
|
|
93
|
+
failure/timeout is not proof of a rollback or of a missing external effect.
|
|
94
|
+
This unit adds no F1 outcome reconciliation, F4 recovery, cross-process exclusion
|
|
95
|
+
or exactly-once external-effect guarantee. InMemory dimension inference and
|
|
96
|
+
backend concurrency constraints retain their documented limits.
|
|
97
|
+
|
|
98
|
+
## Refactoring completion tracking
|
|
99
|
+
|
|
100
|
+
| Contracts | Current boundary status | Remaining work |
|
|
101
|
+
| --- | --- | --- |
|
|
102
|
+
| C10 VectorStore / C11 Embeddings | Common contract behavior implemented in unit 5 | Real Pgvector/Redis/provider service verification remains an implementation gate, reported separately |
|
|
103
|
+
| C05 Context / C07 Persistence / C08 ContentStore / C12 Storage / C13 Execution / C15 Tracing | Main common foundations implemented in units 1-4 | Additional domain acceptance conditions and overall dependency review are not waived |
|
|
104
|
+
| C09 LLM / C06 Tool | Partial | Public values/failures, SDK-neutral operation boundary, Tool SDK inheritance and execution connection |
|
|
105
|
+
| C04 Agent / C01 MultiAgent | Unit 4 ownership boundary implemented | FSM/Runtime/composition dependencies |
|
|
106
|
+
| C02 Workflow | Partial | FSM connection and durable child identity/resume/outcome reconciliation |
|
|
107
|
+
| C03 Generation / C16 Filter / C17 OutputParser | Existing common implementation | Finish responsibility-level conformity review; absence of certification is not evidence that all code is missing |
|
|
108
|
+
|
|
109
|
+
Next implement C09/C06 together where their SDK boundary interacts, then finish
|
|
110
|
+
C04/C01/C02 execution connections and durable collaboration. Inspect the existing
|
|
111
|
+
C03/C16/C17 implementations against explicit conditions before scheduling rewrites.
|
|
112
|
+
|
|
113
|
+
The package records commands actually executed and unexecuted backend gates.
|
|
114
|
+
See [migration](../migrations/r8-unit5.md) and
|
|
115
|
+
[ADR-065](../decisions/065-vector-and-embeddings-common-operations.md).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# r8 unit 6: C09 LLM and C06 Tool
|
|
2
|
+
|
|
3
|
+
Contract placement is determined by ownership of meaning and operations. Reuse
|
|
4
|
+
alone is not a reason to put code into a contract. This unit completes the scoped
|
|
5
|
+
LLM/Tool operation boundary; it does not complete every contract in the target.
|
|
6
|
+
|
|
7
|
+
| Owner | Meaning and operations |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| C09 LLM, `LLMAdapter` | Immutable Request, Message, Response, StreamChunk and TokenUsage; complete/stream templates; input/result/cancellation checks; public failures |
|
|
10
|
+
| C06 Tool, `Tool` | CallRequest, declarations, advertised schema, argument validation/coercion, authorization evaluation and execution/error rules |
|
|
11
|
+
| RubyLLM backend | SDK chat construction, options, message/Tool rendering, chunk/response decoding, SDK exception translation and SDK Tool interception |
|
|
12
|
+
| Agent | Select context, prepare executable Tools, run approval and Tool batches, consume LLM results, persist and recover execution facts |
|
|
13
|
+
| Execution / AsyncClient | Scheduling, cancellation signals, deadlines and worker submission; AsyncClient submits the whole LLM operation |
|
|
14
|
+
|
|
15
|
+
Tool requests are ordinary assistant Response values. They do not authorize or
|
|
16
|
+
execute a Tool. Only the backend knows RubyLLM's message callback and its private
|
|
17
|
+
interception signal. SDK Tool declarations have a rejecting execute method; an
|
|
18
|
+
accidental SDK auto-execution fails instead of bypassing Agent authorization.
|
|
19
|
+
A minimal backend needs only protected perform_complete/perform_stream hooks.
|
|
20
|
+
Agent does not require a Chat-like object, SDK methods or executable Tool handles
|
|
21
|
+
from it. Streaming returns a final Response in addition to typed chunk events.
|
|
22
|
+
|
|
23
|
+
TokenUsage and the four existing LLM failures move from the root namespace into
|
|
24
|
+
LLMAdapter, with no aliases. Unknown usage remains nil, distinct from zero.
|
|
25
|
+
ContextLengthError remains a direct Phronomy::Error; rate limiting and
|
|
26
|
+
authentication remain TransportError subtypes. InvalidResultError identifies
|
|
27
|
+
malformed results rather than a valid empty response. SDK errors retain cause;
|
|
28
|
+
application callback errors and cancellation retain their original identity.
|
|
29
|
+
|
|
30
|
+
`Tool::Base` no longer inherits RubyLLM::Tool. Both `param` and explicit `parameters`
|
|
31
|
+
(Hash/schema DSL) produce a C06 Schema. `validate_arguments` is the public, pure
|
|
32
|
+
preflight operation used before approval; `call` uses the same schema/rules before
|
|
33
|
+
execute. Legacy private type/coercion/nesting algorithms are removed. Parameters
|
|
34
|
+
that were advertised but not enforced by the explicit-schema path now fail before
|
|
35
|
+
approval or execute. See the migration document for the supported schema dialect.
|
|
36
|
+
|
|
37
|
+
SDK initialization, setters, completion and decoding run within AsyncClient's
|
|
38
|
+
worker operation. Cancellation is checked before and after the backend operation,
|
|
39
|
+
after SDK construction, and before delivering chunks. A deadline is an Execution
|
|
40
|
+
cancellation signal. It can settle the caller while a blocking SDK constructor is
|
|
41
|
+
still running; it does not forcibly stop a thread. When that constructor returns,
|
|
42
|
+
the cancellation checkpoint prevents starting a new provider request. Already
|
|
43
|
+
sent external work is not rolled back. Local input_budget uses existing model
|
|
44
|
+
registry metadata; live capacity discovery is not added to the contract.
|
|
45
|
+
|
|
46
|
+
Saved context materializes Phronomy Message/CallRequest values. SDK rendering
|
|
47
|
+
occurs later inside the backend, including structured-content JSON rendering and
|
|
48
|
+
opaque thought_signature metadata. Existing durable thought_signature and usage
|
|
49
|
+
field spellings remain readable. New Tool batch metadata stores the validated
|
|
50
|
+
argument snapshot alongside raw arguments so public authorization projection
|
|
51
|
+
compares what was approved, including coercion and intentional null. Historical
|
|
52
|
+
snapshots retain their explicit old decoding rule. Recovery resolution accepts a Response or its
|
|
53
|
+
canonical Hash, not arbitrary SDK objects. Record identities, transaction/CAS
|
|
54
|
+
rules, approval ownership and F0/F1/F4 classifications remain with Agent and
|
|
55
|
+
Persistence. No exactly-once or automatic retry guarantee is introduced.
|
|
56
|
+
|
|
57
|
+
## Architecture evidence
|
|
58
|
+
|
|
59
|
+
M47 (`llm_contract`) is retired into M15 (`llm_adapter`); the identifier is not
|
|
60
|
+
reused and historical diagrams remain historical. C09 is allowed to reference
|
|
61
|
+
C06 Schema/CallRequest. Directory aggregation also shows C09 -> Tool -> Execution,
|
|
62
|
+
because Tool::Base owns an execution template in the same directory as the values.
|
|
63
|
+
The directory gate permits that specific route; AST checks reject direct C09
|
|
64
|
+
mechanism references, Tool::Base consumption and SDK/Agent/Engine leaks. The full
|
|
65
|
+
Ruby/RBS matrix retains the route instead of hiding it. Standalone loading and a
|
|
66
|
+
minimal backend execution test additionally establish that C09 values do not
|
|
67
|
+
load Tool::Base, Agent, Engine or the SDK.
|
|
68
|
+
|
|
69
|
+
Remaining work includes Agent/MultiAgent/Workflow FSM and Runtime connections,
|
|
70
|
+
Workflow durable children and cross-record outcome evidence, live provider
|
|
71
|
+
verification, and the broader semantic review of existing dependency triangles.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# r8 unit 7: C04 Agent progress and execution connection
|
|
2
|
+
|
|
3
|
+
Contract placement follows ownership of meaning, invariants, operations and
|
|
4
|
+
failures. It is not determined by reuse. This unit improves C04; it does not mark
|
|
5
|
+
all of C04, C06 or the overall target complete.
|
|
6
|
+
|
|
7
|
+
| Owner | Responsibility after this change |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Agent InvocationTransitions | Phase vocabulary, ordered automatic/external transitions, guard evaluation, iteration bound |
|
|
10
|
+
| Agent InvocationActions | Prepared input, LLM dispatch, Tool batch orchestration and result/event interpretation |
|
|
11
|
+
| Agent ExecutionCoordinator / RecoveryCoordinator | Admission, durable preparation, approval, terminal outcome, recovery and causal revision checks |
|
|
12
|
+
| Agent ExecutionEnvironment | Private process-local connection required by the Agent framework; session construction/registration, serial owner and operation submission |
|
|
13
|
+
| Agent EngineEnvironment / EngineSessionBuilder / PhaseMachineBuilder | Runtime registration, EventLoop channel, FSMSession construction and state_machines adaptation |
|
|
14
|
+
| ExecutionReceiver | Serial-owner admission, delivery and lifecycle framework for feature-owned live state |
|
|
15
|
+
| Engine ExecutionReceiverBinding | Concrete EventLoop registration, locking, queued delivery and routing |
|
|
16
|
+
|
|
17
|
+
Previously AgentInvocationSessionBuilder combined Agent entry operations with
|
|
18
|
+
FSMSession creation. PhaseMachineBuilder held automatic progress rules, while
|
|
19
|
+
InvocationTransitions held only external transitions. Execution/recovery also
|
|
20
|
+
selected Runtime.instance repeatedly. The split now leaves both transition sets
|
|
21
|
+
and their priority with Agent. The Engine builder only installs those definitions
|
|
22
|
+
and synchronous entry callbacks into state_machines. InvocationActions retains
|
|
23
|
+
Agent semantics instead of moving the old class wholesale into an adapter.
|
|
24
|
+
|
|
25
|
+
An Agent captures the environment of its ownership registry at construction.
|
|
26
|
+
Execution and recovery reuse it; changing the composition provider does not move
|
|
27
|
+
a live Agent to another Runtime. Cancellation records its durable request before
|
|
28
|
+
posting a notification through that same environment, including after a provider
|
|
29
|
+
change. Detached Agent cancellation is rejected by the existing live-owner check.
|
|
30
|
+
The default provider is installed lazily by runtime_composition/agent_defaults.rb.
|
|
31
|
+
This is an internal composition port, not a new supported application plugin API.
|
|
32
|
+
|
|
33
|
+
ExecutionRegistry remains Agent-owned. Its generic serial receiver framework
|
|
34
|
+
moves from Engine to Execution and receives a channel. The actual EventLoop
|
|
35
|
+
transport stays in Engine. WorkflowExecutionRegistry uses that same channel to
|
|
36
|
+
preserve its existing receiver lifecycle; Workflow policy is not migrated here.
|
|
37
|
+
This placement follows ownership of execution admission/lifecycle, not merely
|
|
38
|
+
that Agent and Workflow share a base class.
|
|
39
|
+
|
|
40
|
+
Provider Call identity is passed explicitly to AgentInvocation from the already
|
|
41
|
+
prepared durable execution. AgentInvocation no longer queries global Runtime to
|
|
42
|
+
find it. FSMSession IDs remain ephemeral routing incarnation IDs. Approval and
|
|
43
|
+
recovery create a fresh session while preserving durable execution/LLM/Tool IDs.
|
|
44
|
+
No storage schema, CAS revision, parent admission, atomicity or F0/F1/F4 policy
|
|
45
|
+
changes. External effects are not exactly-once. Cancel/timeout do not forcibly
|
|
46
|
+
stop workers or undo effects; terminal persistence still waits for physical
|
|
47
|
+
quiescence. Stale session/revision results remain rejected on the serial owner.
|
|
48
|
+
|
|
49
|
+
## Evidence and limits
|
|
50
|
+
|
|
51
|
+
The tests execute the transition policy in a standalone Ruby process without
|
|
52
|
+
Engine or state_machines, enumerate all 32 Tool outcome priority combinations,
|
|
53
|
+
compare the Engine adapter's behavior, and check environment retention and
|
|
54
|
+
cancellation routing. Existing recovery, approval, callback failure, single-writer,
|
|
55
|
+
stale-result and shutdown tests remain part of full/integration validation.
|
|
56
|
+
An AST gate rejects concrete Engine constants and state_machines loading in Agent
|
|
57
|
+
execution, recovery, lifecycle and ExecutionEnvironment. This is a scoped gate,
|
|
58
|
+
not proof that every dependency in the system is correct.
|
|
59
|
+
|
|
60
|
+
The measured graph adds M88/G62 for agent/runtime_binding; retired IDs are not
|
|
61
|
+
reused. Ruby and RBS references remain in the evidence, including cycles caused
|
|
62
|
+
by other uncompleted boundaries. Regenerate the measured diagram from the exact
|
|
63
|
+
candidate; do not treat it as the acyclic target design.
|
|
64
|
+
|
|
65
|
+
Still pending: Agent's Tool child FSM/session builder and its Runtime selection;
|
|
66
|
+
MultiAgent and Workflow FSM/Runtime connections; Workflow durable children and
|
|
67
|
+
cross-record outcome evidence; broader dependency-triangle review. The C06 Tool
|
|
68
|
+
operation/schema contract established in unit 6 remains intact, but its Agent-side
|
|
69
|
+
execution connection is not declared complete by this unit. LLM AsyncClient's
|
|
70
|
+
execution backend selection also remains the existing C09/C13 composition.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# r8 unit 8: C04 Tool child progress and C06 operation boundaries
|
|
2
|
+
|
|
3
|
+
Contract placement follows ownership of domain meaning, invariants and operations.
|
|
4
|
+
C04 owns the lifecycle of a Tool invocation inside an Agent. Calling a Tool does
|
|
5
|
+
not transfer that lifecycle to C06. This unit completes the scoped Tool child FSM
|
|
6
|
+
separation left by unit 7; it does not certify all of C04 or the overall target.
|
|
7
|
+
|
|
8
|
+
| Owner | Responsibility |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| Agent ToolInvocationTransitions | Child phases, ordered automatic/external transitions, legal event sources and recursion bound |
|
|
11
|
+
| Agent ToolInvocationActions / ToolInvocation | Validation/authorization orchestration, approval waiting, dispatch eligibility, outcome application and parent notification |
|
|
12
|
+
| Agent ExecutionEnvironment | The original Agent connection for authorization and default Tool submissions, operation supervision and session creation |
|
|
13
|
+
| Agent ToolSessionBuilder / PhaseMachineBuilder in runtime_binding | Concrete FSMSession/EventSink construction and state_machines adaptation of Agent-owned rules |
|
|
14
|
+
| Tool Operation | Tool execution-mode validity, standard/custom async operation dispatch, completion protocol and result adaptation |
|
|
15
|
+
| Tool ToolExecutor | Default cooperative/offloaded Tool operation, using the injected C13 submission protocol |
|
|
16
|
+
| Execution / _ExecutionSubmitter | Execution submission and completion semantics; concrete resource selection stays in the supplied connection |
|
|
17
|
+
|
|
18
|
+
## What changed
|
|
19
|
+
|
|
20
|
+
ToolInvocationSessionBuilder previously repeated external transitions in both its
|
|
21
|
+
event map and state_machines DSL while also constructing sessions and executing
|
|
22
|
+
Agent entry operations. The new child policy owns one immutable transition set.
|
|
23
|
+
The concrete phase machine and FSMSession source admission read that set. The
|
|
24
|
+
existing parent FSM adapter accepts a policy, so no second domain-aware FSM
|
|
25
|
+
implementation is introduced. Entry operations remain executable Agent code.
|
|
26
|
+
|
|
27
|
+
ToolInvocation now requires its owning execution environment for authorization
|
|
28
|
+
and execution. It no longer selects Runtime.instance, inspects EventLoop, creates
|
|
29
|
+
an ExecutionRegistry connection or selects ToolExecutor. The parent Agent and
|
|
30
|
+
recovery already retain the environment from unit 7; the same environment now
|
|
31
|
+
supplies Tool child entry operations. Authorization captures immutable command
|
|
32
|
+
data before submission. Worker completion delivers an outcome, and serial event
|
|
33
|
+
delivery applies live state.
|
|
34
|
+
|
|
35
|
+
Tool::Operation.call_async is the C06 operation entry for composition-aware
|
|
36
|
+
callers. It selects the standard or custom Tool protocol and validates the
|
|
37
|
+
execution mode and completion handle. Its submitter must implement C13 submit;
|
|
38
|
+
it receives no Agent-specific type. The default offloaded path uses the supplied
|
|
39
|
+
connection, while cooperative work executes inline without a worker. Custom
|
|
40
|
+
call_async implementations keep their existing keyword signature and config,
|
|
41
|
+
return their original handle and continue to own their execution mechanism.
|
|
42
|
+
In particular, an override that calls super still uses the existing Base
|
|
43
|
+
protocol; this change does not inject hidden Runtime state into overrides.
|
|
44
|
+
|
|
45
|
+
Tool::Operation.with_result_transform owns the synchronous/custom-async Tool
|
|
46
|
+
decoration mechanism formerly embedded in Agent::ToolBinding. Agent still chooses
|
|
47
|
+
its configured filters and their meaning. Custom async mapping uses
|
|
48
|
+
AsyncOperation.map and preserves physical completion after logical cancellation.
|
|
49
|
+
As before, an override that itself calls an already decorated synchronous method
|
|
50
|
+
can transform twice; this unit does not rewrite arbitrary application overrides.
|
|
51
|
+
|
|
52
|
+
## Preserved behavior and limits
|
|
53
|
+
|
|
54
|
+
Authorization completion keeps cancelled > failed > rejected > approval wait >
|
|
55
|
+
authorized priority. Execution completion keeps cancelled > failed > completed.
|
|
56
|
+
Validation keeps failure > completed schema handling > authorization. Explicit
|
|
57
|
+
approve/reject/dispatch/cancel events keep their legal source phases.
|
|
58
|
+
Start execution still precedes mark_running!, preserving dispatch eligibility.
|
|
59
|
+
|
|
60
|
+
Approval/recovery create fresh FSMSession routing IDs while retaining durable
|
|
61
|
+
execution, Tool call and invocation IDs. Parent sinks are session-local. This
|
|
62
|
+
change does not alter persistence schema, CAS revisions, approval snapshots,
|
|
63
|
+
causal dispatch preparation, stale-result handling, single-writer ownership or
|
|
64
|
+
terminal persistence after physical quiescence. Cancellation/timeout do not undo
|
|
65
|
+
external effects or forcibly stop workers; exactly-once effects are not promised.
|
|
66
|
+
|
|
67
|
+
The new tests cover all 48 child guard combinations, legal event sources,
|
|
68
|
+
standalone policy loading without Engine/state_machines, worker-result isolation,
|
|
69
|
+
owning-environment submission, fresh recovery routing, custom call_async and
|
|
70
|
+
physical-completion-aware result transformation. Existing parent transition,
|
|
71
|
+
approval, recovery and shutdown suites remain acceptance gates. The AST gate now
|
|
72
|
+
also rejects concrete Engine/FSM references and ToolExecutor selection in Agent
|
|
73
|
+
tool_execution. Static gates are scoped; they do not prove every dependency valid.
|
|
74
|
+
|
|
75
|
+
MultiAgent/Workflow FSM and Runtime connections, Workflow durable children,
|
|
76
|
+
other concrete composition choices, overall dependency review and additional
|
|
77
|
+
live-service/persistence acceptance tests remain. Regenerate the measured graph
|
|
78
|
+
from the exact candidate; target diagrams are not measured dependency evidence.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# R8 unit 9: preserve application-defined Tool result transformations
|
|
2
|
+
|
|
3
|
+
## Ownership
|
|
4
|
+
|
|
5
|
+
The application owns which transformations run, their order and their
|
|
6
|
+
multiplicity. Agent's ToolBinding captures and composes its configured filters.
|
|
7
|
+
C06 Tool owns the operation/decorator mechanism that executes that composition.
|
|
8
|
+
C13 Execution owns completion adaptation, failure/cancellation propagation and
|
|
9
|
+
physical-completion tracking. Shared use is not the reason for C06 ownership.
|
|
10
|
+
|
|
11
|
+
There is no universal "one filter per public invocation" policy. Each configured
|
|
12
|
+
stage must retain its position and multiplicity. Registering the same filter
|
|
13
|
+
twice or nesting result decorators remains meaningful application composition.
|
|
14
|
+
|
|
15
|
+
## Defect
|
|
16
|
+
|
|
17
|
+
In unit 7 and unit 8 a custom call_async delegating with super reached Base's
|
|
18
|
+
default async bridge, which invoked the decorated synchronous call. A second
|
|
19
|
+
decoration then transformed the custom async completion. One configured stage
|
|
20
|
+
therefore ran twice. If the custom implementation additionally mapped the result,
|
|
21
|
+
the first transformation also ran on an intermediate value rather than the
|
|
22
|
+
custom operation's final result.
|
|
23
|
+
|
|
24
|
+
## Internal delegation
|
|
25
|
+
|
|
26
|
+
Operation.with_result_transform records the exact synchronous wrapper method
|
|
27
|
+
only when that decorator also installs an async completion wrapper. Base's
|
|
28
|
+
call_async obtains a bound synchronous delegate from Operation. That delegate
|
|
29
|
+
skips the leading framework wrappers whose async counterparts already own their
|
|
30
|
+
stages. ToolExecutor receives the callable explicitly and invokes it inline or
|
|
31
|
+
inside the submitted worker, on the original Tool instance.
|
|
32
|
+
|
|
33
|
+
Selection stops at application methods and sync-only decorator stages. Exact
|
|
34
|
+
method matching avoids bypassing a later application replacement, including a
|
|
35
|
+
singleton call override. No Thread/Fiber local flag, per-instance busy flag,
|
|
36
|
+
cloning, value tagging, equality check or filter-identity deduplication is used.
|
|
37
|
+
|
|
38
|
+
## Application calls remain application calls
|
|
39
|
+
|
|
40
|
+
Only Base's standard async-to-sync bridge is internal delegation. A custom
|
|
41
|
+
implementation that explicitly calls the public call method invokes that
|
|
42
|
+
method's configured transformations. Its async completion can then have its own
|
|
43
|
+
transformation. The framework does not guess whether the application intended
|
|
44
|
+
that explicit call to be raw execution.
|
|
45
|
+
|
|
46
|
+
For example, with a bracket transform:
|
|
47
|
+
|
|
48
|
+
| Composition | Result for x |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| One stage, custom call_async delegates using super | [x] |
|
|
51
|
+
| Two registrations of the bracket transform | [[x]] |
|
|
52
|
+
| Custom maps super's raw value to custom:x, then one stage | [custom:x] |
|
|
53
|
+
| Custom explicitly calls the decorated public call and prefixes custom: | [custom:[x]] |
|
|
54
|
+
|
|
55
|
+
Applications wanting Base's normal execution as an implementation step should
|
|
56
|
+
use super. Applications can also call their configured filters explicitly; those
|
|
57
|
+
calls are never deduplicated. A custom override inserted between decorators is
|
|
58
|
+
an application boundary, not a wrapper the framework may silently bypass.
|
|
59
|
+
|
|
60
|
+
## Preserved completion contract
|
|
61
|
+
|
|
62
|
+
Custom completions still use AsyncOperation.map. Original failures retain their
|
|
63
|
+
identity, source cancellation remains cancellation, and physical completion waits
|
|
64
|
+
for both source work and active transformations. Cancelling a mapped result still
|
|
65
|
+
does not implicitly cancel its source. Default cooperative/offloaded dispatch,
|
|
66
|
+
the owning submitter, public keyword arguments, effective names, receiver state,
|
|
67
|
+
and schema/authorization rules remain intact.
|
|
68
|
+
|
|
69
|
+
## Scope
|
|
70
|
+
|
|
71
|
+
This is a core-only correction. Public signatures and stored schemas are unchanged.
|
|
72
|
+
It does not complete the remaining C01/C02 connections, all C04 composition,
|
|
73
|
+
the source dependency cycles, or the broader acceptance gates.
|