phronomy 0.25.0 → 0.27.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/CHANGELOG.md +71 -0
- data/CONTRIBUTING.md +4 -4
- data/README.md +14 -7
- data/VERIFY.sh +27 -27
- data/benchmark/bench_agent_invoke.rb +26 -22
- data/benchmark/bench_context_assembler.rb +4 -5
- data/benchmark/bench_regression.rb +1 -1
- data/docs/architecture/agent-chat-and-state-ownership.md +147 -0
- data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
- data/docs/architecture/agent-context.md +5 -3
- data/docs/architecture/agent-transition-ownership.md +89 -0
- data/docs/architecture/before-llm-input.md +6 -0
- data/docs/architecture/context-management.md +30 -0
- data/docs/architecture/context-preparation-steps.md +90 -0
- data/docs/architecture/entry-action-and-team-wording.md +72 -0
- data/docs/architecture/execution-metadata-and-values.md +80 -0
- data/docs/architecture/generator-verifier-ownership.md +111 -0
- data/docs/architecture/multi-agent-handoff.md +8 -2
- data/docs/architecture/persistence-refactoring-plan.md +50 -0
- data/docs/architecture/persistence.md +29 -6
- data/docs/architecture/refactoring-closure.md +334 -0
- data/docs/architecture/remaining-refactoring-plan.md +374 -0
- data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
- data/docs/architecture/tool-schema-recording-gap.md +50 -0
- data/docs/architecture/tracing.md +4 -4
- data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
- data/docs/architecture.md +209 -0
- data/docs/async-composition.md +205 -0
- data/docs/decisions/010-cooperative-first-concurrency.md +23 -23
- data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
- 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/030-agent-handoff-domain-and-durable-responsibility.md +5 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +5 -0
- data/docs/decisions/032-storage-backend-composition.md +80 -0
- data/docs/decisions/033-domain-persistence-ownership.md +79 -0
- data/docs/decisions/034-handoff-runner-coordination-ownership.md +76 -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 +131 -0
- data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +74 -0
- data/docs/decisions/040-configuration-default-composition.md +94 -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 +100 -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 +151 -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 +78 -0
- data/docs/decisions/README.md +35 -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/features.md +21 -12
- data/docs/getting-started.md +10 -10
- data/docs/migrations/0.15.md +5 -0
- data/docs/migrations/durable-semantic-coordination-v2.md +7 -1
- data/docs/migrations/handoff-runner-multi-agent.md +35 -0
- data/docs/migrations/neutral-storage-spi.md +43 -0
- data/docs/migrations/parallel-tool-chat-removal.md +49 -0
- data/docs/migrations/shared-state-multi-agent.md +44 -0
- data/docs/migrations/storage-backend-composition.md +117 -0
- data/docs/migrations/storage-transaction-boundaries.md +74 -0
- data/docs/persistence-backends.md +162 -204
- data/docs/runtime-and-concurrency.md +205 -60
- data/lib/phronomy/agent/api/agent.rb +17 -0
- data/lib/phronomy/agent/async_event_api.rb +2 -2
- data/lib/phronomy/agent/base.rb +55 -251
- data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
- data/lib/phronomy/agent/context/capability/base.rb +67 -26
- data/lib/phronomy/agent/context/capability/tool_executor.rb +62 -0
- data/lib/phronomy/agent/{context_assembler.rb → context_assembly/context_assembler.rb} +143 -88
- data/lib/phronomy/agent/{context_importer.rb → context_assembly/context_importer.rb} +2 -2
- data/lib/phronomy/agent/{ruby_llm_materializer.rb → context_assembly/ruby_llm_materializer.rb} +4 -7
- data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +36 -0
- data/lib/phronomy/agent/context_assembly/saved_context_reader.rb +53 -0
- data/lib/phronomy/agent/context_assembly/state_writer.rb +165 -0
- data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +22 -0
- data/lib/phronomy/agent/{context_plan.rb → context_contract/context_plan.rb} +1 -1
- data/lib/phronomy/agent/{context_policy_input.rb → context_contract/context_policy_input.rb} +6 -6
- data/lib/phronomy/agent/{llm_input_build_context.rb → context_contract/llm_input_build_context.rb} +1 -1
- data/lib/phronomy/agent/{llm_input_manifest.rb → context_contract/llm_input_manifest.rb} +20 -20
- data/lib/phronomy/agent/{llm_input_patch.rb → context_contract/llm_input_patch.rb} +2 -2
- data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
- data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +8 -13
- data/lib/phronomy/agent/{agent_invocation_session_builder.rb → execution/agent_invocation_session_builder.rb} +20 -96
- data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +305 -0
- data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +12 -13
- data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +2 -3
- data/lib/phronomy/agent/execution/execution_coordinator.rb +1925 -0
- data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
- data/lib/phronomy/agent/execution/execution_metadata.rb +53 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +344 -0
- data/lib/phronomy/agent/execution/execution_registry.rb +459 -0
- data/lib/phronomy/agent/execution/execution_session_runner.rb +118 -0
- data/lib/phronomy/agent/execution/initial_preparation.rb +421 -0
- data/lib/phronomy/agent/execution/invocation_transitions.rb +86 -0
- data/lib/phronomy/agent/{phase_machine_builder.rb → execution/phase_machine_builder.rb} +22 -73
- data/lib/phronomy/agent/{provider_call_outcome.rb → execution/provider_call_outcome.rb} +9 -9
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
- data/lib/phronomy/agent/{handoff_context.rb → handoff/handoff_context.rb} +2 -2
- data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +15 -0
- data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +131 -0
- data/lib/phronomy/agent/{handoff_state.rb → handoff/handoff_state.rb} +1 -1
- 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/{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 -10
- data/lib/phronomy/{agent_already_exists_error.rb → agent/lifecycle_contract/agent_already_exists_error.rb} +2 -0
- data/lib/phronomy/{agent_busy_error.rb → agent/lifecycle_contract/agent_busy_error.rb} +2 -0
- data/lib/phronomy/{agent_purged_error.rb → agent/lifecycle_contract/agent_purged_error.rb} +2 -0
- data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +7 -0
- data/lib/phronomy/{stream_callback_error.rb → agent/lifecycle_contract/stream_callback_error.rb} +2 -0
- data/lib/phronomy/agent/persistence/agent_repository.rb +61 -0
- data/lib/phronomy/agent/persistence/codec.rb +358 -0
- data/lib/phronomy/agent/persistence/execution_repository.rb +108 -0
- data/lib/phronomy/agent/persistence/handoff_state_repository.rb +58 -0
- data/lib/phronomy/agent/persistence/journal_repository.rb +54 -0
- data/lib/phronomy/agent/persistence/queries.rb +61 -0
- data/lib/phronomy/agent/persistence/storage_schema.rb +24 -0
- data/lib/phronomy/agent/persistence/watermark.rb +27 -0
- data/lib/phronomy/agent/recovery/invocation_restorer.rb +132 -0
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +21 -45
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +36 -41
- data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +37 -40
- data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +9 -13
- data/lib/phronomy/agent/recovery/recovery_support.rb +227 -0
- data/lib/phronomy/agent/selection/candidate.rb +1 -1
- 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 +90 -0
- data/lib/phronomy/agent/{tool_call_intercepted.rb → tool_execution/tool_call_intercepted.rb} +2 -2
- data/lib/phronomy/agent/{tool_definition_set.rb → tool_execution/tool_definition_set.rb} +9 -4
- data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +69 -34
- data/lib/phronomy/agent/{tool_invocation_session_builder.rb → tool_execution/tool_invocation_session_builder.rb} +2 -2
- 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.rb → configuration/configuration.rb} +14 -5
- data/lib/phronomy/configuration/global_configuration.rb +26 -0
- data/lib/phronomy/content_store/storage_schema.rb +11 -0
- data/lib/phronomy/content_store/stored_contents.rb +43 -0
- data/lib/phronomy/engine/backpressure_error.rb +7 -0
- data/lib/phronomy/{blocking.rb → engine/blocking.rb} +15 -8
- data/lib/phronomy/engine/cancellation_error.rb +7 -0
- data/lib/phronomy/engine/concurrency/cancellation_token.rb +4 -0
- data/lib/phronomy/engine/concurrency/offload_pool.rb +29 -16
- data/lib/phronomy/engine/concurrency/operation_binding.rb +43 -0
- data/lib/phronomy/engine/concurrency/physical_completion_task.rb +4 -62
- data/lib/phronomy/engine/concurrency/result_collector.rb +99 -0
- data/lib/phronomy/engine/concurrency/result_composition.rb +145 -0
- data/lib/phronomy/engine/concurrency/subscriptions.rb +68 -0
- data/lib/phronomy/engine/concurrency/worker_input_restricted.rb +14 -0
- data/lib/phronomy/engine/event_loop.rb +160 -626
- data/lib/phronomy/engine/event_loop_reentrancy_error.rb +8 -0
- data/lib/phronomy/engine/execution.rb +229 -0
- data/lib/phronomy/engine/execution_cancellation_error.rb +14 -0
- data/lib/phronomy/engine/execution_receiver.rb +65 -0
- data/lib/phronomy/engine/execution_timeout_error.rb +14 -0
- data/lib/phronomy/engine/fsm_protocol.rb +14 -0
- data/lib/phronomy/engine/fsm_session.rb +38 -31
- data/lib/phronomy/{invalid_async_entry_action_error.rb → engine/invalid_async_entry_action_error.rb} +3 -1
- data/lib/phronomy/{invalid_async_transition_action_error.rb → engine/invalid_async_transition_action_error.rb} +3 -1
- data/lib/phronomy/{invalid_async_workflow_action_error.rb → engine/invalid_async_workflow_action_error.rb} +3 -1
- data/lib/phronomy/{invocation_context.rb → engine/invocation_context.rb} +13 -1
- data/lib/phronomy/engine/pool_shutdown_error.rb +7 -0
- data/lib/phronomy/engine/recursion_limit_error.rb +7 -0
- data/lib/phronomy/engine/runtime/timer_queue.rb +11 -0
- data/lib/phronomy/engine/runtime.rb +80 -84
- data/lib/phronomy/engine/runtime_shutdown_error.rb +7 -0
- data/lib/phronomy/engine/runtime_shutdown_reentrancy_error.rb +7 -0
- data/lib/phronomy/engine/scheduler_reentrancy_error.rb +9 -0
- data/lib/phronomy/engine/{task.rb → task_result.rb} +101 -42
- data/lib/phronomy/engine/timeout_error.rb +7 -0
- data/lib/phronomy/filter/contract/filter_block_error.rb +14 -0
- data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -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/base.rb +2 -2
- data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
- data/lib/phronomy/llm_contract/authentication_error.rb +7 -0
- data/lib/phronomy/{context_budget_exceeded_error.rb → llm_contract/context_budget_exceeded_error.rb} +2 -0
- data/lib/phronomy/llm_contract/context_length_error.rb +7 -0
- data/lib/phronomy/llm_contract/rate_limit_error.rb +7 -0
- data/lib/phronomy/{token_usage.rb → llm_contract/token_usage.rb} +2 -2
- data/lib/phronomy/llm_contract/transport_error.rb +7 -0
- data/lib/phronomy/multi_agent/admission_registry.rb +22 -2
- data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +8 -8
- data/lib/phronomy/{agent → multi_agent}/handoff_runner.rb +18 -17
- data/lib/phronomy/multi_agent/orchestrator.rb +36 -68
- data/lib/phronomy/multi_agent/persistence/codec.rb +55 -0
- data/lib/phronomy/multi_agent/persistence/queries.rb +30 -0
- data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +108 -0
- data/lib/phronomy/multi_agent/persistence/team_repository.rb +61 -0
- data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
- data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +15 -0
- data/lib/phronomy/multi_agent/team_coordinator.rb +21 -18
- data/lib/phronomy/multi_agent/team_execution.rb +1 -1
- data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +14 -4
- data/lib/phronomy/multi_agent/team_root.rb +1 -1
- data/lib/phronomy/output_parser/contract/parse_error.rb +7 -0
- data/lib/phronomy/persistence/api/persistence.rb +140 -0
- data/lib/phronomy/persistence/migration/initial_format_migration.rb +19 -19
- data/lib/phronomy/persistence_composition/repositories.rb +77 -0
- data/lib/phronomy/persistence_composition/storage_schema.rb +24 -0
- data/lib/phronomy/{execution_rehydration_required_error.rb → recovery/execution_rehydration_required_error.rb} +2 -0
- data/lib/phronomy/{recovery.rb → recovery/recovery.rb} +1 -1
- data/lib/phronomy/runtime_composition/agent_defaults.rb +7 -0
- data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
- data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
- data/lib/phronomy/storage/backend.rb +101 -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/scorer/llm_judge.rb +5 -3
- data/lib/phronomy/testing/fake_clock.rb +13 -9
- data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +4 -4
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +10 -7
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +2 -2
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +8 -8
- data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
- data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +123 -0
- data/lib/phronomy/testing/persistence_contract.rb +4 -0
- data/lib/phronomy/tool/contract/tool_error.rb +7 -0
- data/lib/phronomy/tools/agent.rb +6 -6
- data/lib/phronomy/vector_store/async_backend.rb +5 -5
- data/lib/phronomy/vector_store/embeddings/base.rb +2 -2
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +10 -8
- data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +4 -0
- data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
- data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +188 -0
- data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +126 -75
- data/lib/phronomy/workflow/execution/workflow_terminal_policy.rb +40 -0
- data/lib/phronomy/workflow/persistence/codec.rb +153 -0
- data/lib/phronomy/workflow/persistence/state_repository.rb +57 -0
- data/lib/phronomy/workflow/phase_machine_builder.rb +8 -8
- data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +9 -0
- data/lib/phronomy.rb +52 -94
- data/scripts/api_snapshot.rb +4 -2
- data/scripts/storage_spi_snapshot.rb +36 -0
- data/sig/phronomy/agent.rbs +4 -5
- data/sig/phronomy/execution_receiver.rbs +34 -0
- data/sig/phronomy/extensions.rbs +5 -5
- data/sig/phronomy/handoff.rbs +4 -2
- data/sig/phronomy/multi_agent.rbs +19 -3
- data/sig/phronomy/persistence.rbs +7 -91
- data/sig/phronomy/runtime.rbs +34 -7
- data/sig/phronomy/storage.rbs +174 -0
- data/sig/phronomy/tool.rbs +11 -2
- data/sig/phronomy/workflow.rbs +1 -1
- metadata +236 -99
- data/lib/phronomy/agent/execution_coordinator.rb +0 -3138
- data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
- data/lib/phronomy/agent/recovery_support.rb +0 -504
- data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
- data/lib/phronomy/agent/tool_executor.rb +0 -55
- data/lib/phronomy/generator_verifier.rb +0 -369
- data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
- data/lib/phronomy/multi_agent/fan_out_invocation.rb +0 -137
- data/lib/phronomy/multi_agent/fan_out_session_builder.rb +0 -118
- 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/ruby_llm_patches.rb +0 -24
- data/lib/phronomy/workflow_recovery.rb +0 -123
- /data/lib/phronomy/agent/{context_candidate_resolver.rb → context_assembly/context_candidate_resolver.rb} +0 -0
- /data/lib/phronomy/agent/{context_policy_input_builder.rb → context_assembly/context_policy_input_builder.rb} +0 -0
- /data/lib/phronomy/agent/{context_plan_validator.rb → context_contract/context_plan_validator.rb} +0 -0
- /data/lib/phronomy/agent/{context_policy.rb → context_contract/context_policy.rb} +0 -0
- /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
- /data/lib/phronomy/agent/{handoff.rb → handoff/handoff.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_capability_factory.rb → handoff/handoff_capability_factory.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_policy.rb → handoff/handoff_policy.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_projection.rb → handoff/handoff_projection.rb} +0 -0
- /data/lib/phronomy/agent/{handoff_request.rb → handoff/handoff_request.rb} +0 -0
- /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
- /data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +0 -0
- /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
- /data/lib/phronomy/{metrics.rb → engine/metrics.rb} +0 -0
- /data/lib/phronomy/{runnable.rb → engine/runnable.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '095ac1376e77f34201dceeafec7dc114340aa2cae7cd8f1bb2bb7c2552e64e87'
|
|
4
|
+
data.tar.gz: 4d900c3bdc20e3fb0210046daffc4d78d1b990f118281c04037cc45beca2d699
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3108c48424885f72ea256e6c7cd7dfa8a7230647727f288f9fce840ee9309a51b523e64748663a7d1341e88b0c05cfe5432cb91a521039b16f28b0e2c14a4714
|
|
7
|
+
data.tar.gz: 51795e8c019cb92d8a17eadb864b726f9359ed1c963b06acfb52cb7440b99234755ad2c7e169a5afb8e5958ea45b99635d9035eea4d3c4ceb84ac4d554fdc814
|
data/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,77 @@ Release history for 0.14.0 and earlier is archived in
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## [0.27.0] - 2026-09-24
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Separate application Runtime reset and configuration replacement into
|
|
22
|
+
`runtime_composition/global_runtime.rb`. Configuration access no longer owns
|
|
23
|
+
Runtime lifecycle control; the reset API, shutdown ordering, timeout behavior,
|
|
24
|
+
and configuration defaults are unchanged. See
|
|
25
|
+
[ADR-039](docs/decisions/039-runtime-configuration-lifecycle-ownership.md).
|
|
26
|
+
- Group root implementations and entry-point exceptions by responsibility:
|
|
27
|
+
common definitions, Engine/FSM execution contracts, Recovery, Workflow,
|
|
28
|
+
Agent lifecycle contracts, LLM contracts, configuration, and feature APIs.
|
|
29
|
+
Preserve public constant names, API signatures, stored formats, and lifecycle
|
|
30
|
+
loading. Reserve the direct source root for version and namespace/loading
|
|
31
|
+
files; share the three equivalent immutable-copy helpers. See
|
|
32
|
+
[ADR-038](docs/decisions/038-responsibility-based-source-layout.md).
|
|
33
|
+
- Move the shared `Phronomy::Error` base exception to `common/error.rb` and
|
|
34
|
+
define ownership rules for general common definitions. The public constant,
|
|
35
|
+
subclass hierarchies, and rescue behavior are preserved. See
|
|
36
|
+
[ADR-037](docs/decisions/037-common-definition-ownership.md).
|
|
37
|
+
- Group Context Policy and hook contracts, values, Manifest representation,
|
|
38
|
+
and Plan validation under `agent/context_contract/`. Zeitwerk collapses the
|
|
39
|
+
directory so the existing `Phronomy::Agent` constant names, Policy/hook
|
|
40
|
+
protocols, and Manifest format remain unchanged. Agent execution and Context
|
|
41
|
+
assembly retain their existing responsibilities. See
|
|
42
|
+
[ADR-036](docs/decisions/036-context-contract-ownership.md).
|
|
43
|
+
- Move the internal `Phronomy::Agent::ToolExecutor` to
|
|
44
|
+
`Phronomy::Agent::Context::Capability::ToolExecutor`, alongside the default
|
|
45
|
+
Tool invocation contract, without an alias for the old internal constant.
|
|
46
|
+
Public Tool names, `call_async` arguments, execution modes, Runtime routing,
|
|
47
|
+
and Agent-owned authorization/result handling are preserved. See
|
|
48
|
+
[ADR-035](docs/decisions/035-tool-executor-capability-ownership.md).
|
|
49
|
+
- Move `Phronomy::Agent::HandoffRunner` to
|
|
50
|
+
`Phronomy::MultiAgent::HandoffRunner` without a compatibility alias on the
|
|
51
|
+
architecture refactoring branch. Handoff edges and Policy remain in Agent;
|
|
52
|
+
execution, persistence formats, cancellation and recovery behavior are unchanged.
|
|
53
|
+
See [the migration guide](docs/migrations/handoff-runner-multi-agent.md).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## [0.26.0] - 2026-09-14
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
|
|
61
|
+
- Rename the public completion type to `Phronomy::TaskResult`; remove `Task`
|
|
62
|
+
without a compatibility alias in this development release.
|
|
63
|
+
- Remove `Orchestrator#fan_out` and `#fan_out_async`. Use `dispatch_parallel`
|
|
64
|
+
for Agent-specific construction/knowledge/concurrency policy, or Execution
|
|
65
|
+
for application-defined JOB composition.
|
|
66
|
+
- Preserve cancelled states and original cancellation errors across result
|
|
67
|
+
transformations, independently of failures that carry CancellationError.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- `TaskResult#flat_map`, `.all_settled`, and immutable input-order Outcome records.
|
|
72
|
+
- `Execution.run_async` / `.run` for shared runtime fan-out/fan-in, explicit
|
|
73
|
+
invocation context, whole-execution timeout/cancellation and partial snapshots.
|
|
74
|
+
- `Execution#observe` for scoped continuations of externally owned results.
|
|
75
|
+
- Optional `invocation_context:` on `Blocking.call_async`, with one-way combined
|
|
76
|
+
context and individual controls shared with Agent admission.
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- Dispose finished execution subscriptions and timers while retaining required
|
|
81
|
+
physical completion tracking. Orchestrator reuses the common Execution engine.
|
|
82
|
+
|
|
83
|
+
See [Result composition and Execution](docs/async-composition.md) for migration,
|
|
84
|
+
completion boundaries, cancellation and application responsibilities.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
17
88
|
## [0.25.0] - 2026-09-12
|
|
18
89
|
|
|
19
90
|
### Added
|
data/CONTRIBUTING.md
CHANGED
|
@@ -98,16 +98,16 @@ Do not change Ruby visibility merely to make it match an `@api` annotation.
|
|
|
98
98
|
|
|
99
99
|
### Async completion boundary
|
|
100
100
|
|
|
101
|
-
`Phronomy::
|
|
101
|
+
`Phronomy::TaskResult` is the caller-facing completion handle. EventLoop/FSMSession and
|
|
102
102
|
OffloadPool are execution/continuation mechanisms, not competing completion
|
|
103
103
|
abstractions.
|
|
104
104
|
|
|
105
105
|
Synchronous work that requires execution away from EventLoop must use an
|
|
106
106
|
OffloadPool. Do not create production worker Threads in adapters, backends, or
|
|
107
107
|
Tools to emulate asynchronous behavior. Logical waits between Phronomy
|
|
108
|
-
lifecycles stay on EventLoop/FSMSession and settle a
|
|
108
|
+
lifecycles stay on EventLoop/FSMSession and settle a TaskResult later.
|
|
109
109
|
|
|
110
|
-
The framework owns
|
|
110
|
+
The framework owns TaskResult settlement (`complete`, `fail`, and framework-driven
|
|
111
111
|
cancellation). Application code should observe Tasks through `wait_result`,
|
|
112
112
|
`on_complete`, `map`, and settlement state. Operation-wide cancellation of
|
|
113
113
|
OffloadPool work is supplied through `CancellationToken`.
|
|
@@ -149,7 +149,7 @@ ambiguous. Do not renumber historical ADRs to repair that legacy collision.
|
|
|
149
149
|
|
|
150
150
|
For Agent Context work, ADR-012 and ADR-013 define the current Journal,
|
|
151
151
|
Manifest, Context Policy and persistent Knowledge model. ADR-010 defines the
|
|
152
|
-
EventLoop/FSMSession,
|
|
152
|
+
EventLoop/FSMSession, TaskResult, and OffloadPool execution boundary. ADR-015 defines
|
|
153
153
|
the Tool public façade, extension-SPI boundary, and RBS ownership rules.
|
|
154
154
|
|
|
155
155
|
Current explanatory architecture starts at [`docs/architecture.md`](docs/architecture.md).
|
data/README.md
CHANGED
|
@@ -22,8 +22,10 @@ tracking `main` directly.
|
|
|
22
22
|
- **Multi-Agent Handoff** — semantic Source-to-Target responsibility transfer with policy-bounded Context projection and persisted active responsibility and exact Target recovery within one Persistence domain.
|
|
23
23
|
- **EventLoop + FSMSession** — the framework control plane for logical lifecycle coordination.
|
|
24
24
|
- **OffloadPool** — bounded operating-system-thread execution boundary for synchronous work that must not run on EventLoop.
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
25
|
+
- **TaskResult** — the common thread-free completion handle returned by Phronomy asynchronous APIs, including OffloadPool-backed work.
|
|
26
|
+
- **TaskResult.completed / TaskResult.failed** — already-settled application results without starting execution.
|
|
27
|
+
- **TaskResult.map / flat_map / all_settled** — result transformation, asynchronous chaining and ordered all-settled observation.
|
|
28
|
+
- **Execution.run_async / run** — start application JOBs and join their final results under a whole-execution timeout and cancellation scope.
|
|
27
29
|
- **Blocking.call_async** — submits synchronous application work to the existing bounded OffloadPool without waiting for queue space.
|
|
28
30
|
- **Journal / Context Policy / Manifest** — canonical history plus per-LLM-call context selection.
|
|
29
31
|
|
|
@@ -43,6 +45,10 @@ Then run:
|
|
|
43
45
|
bundle install
|
|
44
46
|
```
|
|
45
47
|
|
|
48
|
+
This refactoring branch requires RubyLLM 2.0.x. See the
|
|
49
|
+
[RubyLLM 2 and token-ownership migration](docs/architecture/rubyllm-2-token-ownership.md)
|
|
50
|
+
for removed input-budget overrides and the in-flight Tool-manifest upgrade boundary.
|
|
51
|
+
|
|
46
52
|
Configure RubyLLM with the provider credentials and transport policy required by
|
|
47
53
|
your application. Phronomy does not add another LLM transport retry/timeout layer.
|
|
48
54
|
|
|
@@ -86,8 +92,8 @@ class. The legacy `Phronomy::Agent::Context::Capability::Base` constant remains
|
|
|
86
92
|
valid for compatibility.
|
|
87
93
|
|
|
88
94
|
For non-blocking top-level use, call `invoke_async` and keep the returned
|
|
89
|
-
`Phronomy::
|
|
90
|
-
another
|
|
95
|
+
`Phronomy::TaskResult`. Inside Phronomy lifecycle callbacks, do not block waiting for
|
|
96
|
+
another TaskResult; continue through explicit events instead.
|
|
91
97
|
|
|
92
98
|
```ruby
|
|
93
99
|
task = ResearchAgent.new.invoke_async("Research Ruby AI frameworks")
|
|
@@ -128,14 +134,14 @@ Runtime
|
|
|
128
134
|
└─ EventLoop-driven timers
|
|
129
135
|
|
|
130
136
|
EventLoop / FSMSession ─┐
|
|
131
|
-
├─>
|
|
137
|
+
├─> TaskResult = completion handle
|
|
132
138
|
OffloadPool ────────────┘
|
|
133
139
|
```
|
|
134
140
|
|
|
135
141
|
Logical waiting remains in EventLoop/FSMSession state. Synchronous work that
|
|
136
142
|
would block EventLoop uses the bounded OffloadPool. OffloadPool-specific queue,
|
|
137
143
|
worker, timeout, and abandonment state remains private runtime machinery; callers
|
|
138
|
-
observe completion through `Phronomy::
|
|
144
|
+
observe completion through `Phronomy::TaskResult`. See
|
|
139
145
|
[Runtime and concurrency](docs/runtime-and-concurrency.md) for the detailed
|
|
140
146
|
contracts, timeout/cancellation semantics, metrics, and callback rules.
|
|
141
147
|
|
|
@@ -144,7 +150,8 @@ contracts, timeout/cancellation semantics, metrics, and callback rules.
|
|
|
144
150
|
- [Getting started](docs/getting-started.md) — installation, RubyLLM setup, Agent/Workflow basics, persistence, streaming.
|
|
145
151
|
- [Features and API stability](docs/features.md) — public feature matrix and stability labels.
|
|
146
152
|
- [Architecture](docs/architecture.md) — canonical current explanatory architecture entry and authority navigation.
|
|
147
|
-
- [Runtime and concurrency](docs/runtime-and-concurrency.md) — EventLoop, FSMSession,
|
|
153
|
+
- [Runtime and concurrency](docs/runtime-and-concurrency.md) — EventLoop, FSMSession, TaskResult, OffloadPool, cancellation, observability.
|
|
154
|
+
- [Result composition and Execution](docs/async-composition.md) — application JOBs, map/flat_map, fan-in snapshots, context ownership and migration.
|
|
148
155
|
- [MCP client](docs/mcp-client.md) — Model Context Protocol (MCP) integration and supported schema subset.
|
|
149
156
|
- [Migration from 0.15-era APIs](docs/migrations/0.15.md).
|
|
150
157
|
- [0.16 cleanup migration](docs/migrations/0.16.md).
|
data/VERIFY.sh
CHANGED
|
@@ -21,9 +21,9 @@ required_files=(
|
|
|
21
21
|
docs/decisions/024-event-loop-single-writer-agent-runtime.md
|
|
22
22
|
docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md
|
|
23
23
|
docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md
|
|
24
|
-
lib/phronomy/workflow.rb
|
|
25
|
-
lib/phronomy/workflow_context.rb
|
|
26
|
-
lib/phronomy/workflow_runner.rb
|
|
24
|
+
lib/phronomy/workflow/execution/workflow.rb
|
|
25
|
+
lib/phronomy/workflow/execution/workflow_context.rb
|
|
26
|
+
lib/phronomy/workflow/execution/workflow_runner.rb
|
|
27
27
|
lib/phronomy/engine/event_loop.rb
|
|
28
28
|
lib/phronomy/engine/fsm_session.rb
|
|
29
29
|
lib/phronomy/persistence/in_memory.rb
|
|
@@ -38,16 +38,16 @@ required_files=(
|
|
|
38
38
|
spec/phronomy/persistence/initial_format_migration_spec.rb
|
|
39
39
|
lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb
|
|
40
40
|
spec/phronomy/workflow_identity_contract_spec.rb
|
|
41
|
-
lib/phronomy/invocation_context.rb
|
|
41
|
+
lib/phronomy/engine/invocation_context.rb
|
|
42
42
|
lib/phronomy/agent/async_event_api.rb
|
|
43
43
|
lib/phronomy/agent/execution_coordinator.rb
|
|
44
44
|
lib/phronomy/agent/journal_record.rb
|
|
45
45
|
lib/phronomy/agent/context_assembler.rb
|
|
46
|
-
lib/phronomy/agent/context_policy.rb
|
|
47
|
-
lib/phronomy/agent/context_policy_input.rb
|
|
46
|
+
lib/phronomy/agent/context_contract/context_policy.rb
|
|
47
|
+
lib/phronomy/agent/context_contract/context_policy_input.rb
|
|
48
48
|
lib/phronomy/agent/context_policy_input_builder.rb
|
|
49
|
-
lib/phronomy/agent/context_plan.rb
|
|
50
|
-
lib/phronomy/agent/context_plan_validator.rb
|
|
49
|
+
lib/phronomy/agent/context_contract/context_plan.rb
|
|
50
|
+
lib/phronomy/agent/context_contract/context_plan_validator.rb
|
|
51
51
|
lib/phronomy/agent/context_policies/default.rb
|
|
52
52
|
spec/phronomy/agent/context_policy_architecture_regression_spec.rb
|
|
53
53
|
lib/phronomy/agent/agent_invocation.rb
|
|
@@ -68,7 +68,7 @@ required_files=(
|
|
|
68
68
|
spec/phronomy/workflow/admission_spec.rb
|
|
69
69
|
spec/phronomy/workflow/live_signal_spec.rb
|
|
70
70
|
spec/phronomy/workflow/transition_action_spec.rb
|
|
71
|
-
lib/phronomy/generator_verifier.rb
|
|
71
|
+
lib/phronomy/generation/generator_verifier.rb
|
|
72
72
|
spec/phronomy/generator_verifier_spec.rb
|
|
73
73
|
spec/integration/subgraph_parallel_agent_tool_spec.rb
|
|
74
74
|
lib/phronomy/tracing/base.rb
|
|
@@ -87,11 +87,11 @@ required_files=(
|
|
|
87
87
|
spec/phronomy/fault_injection_advanced_spec.rb
|
|
88
88
|
spec/phronomy/persistence_architecture_regression_spec.rb
|
|
89
89
|
lib/phronomy/agent/base.rb
|
|
90
|
-
lib/phronomy/agent_already_exists_error.rb
|
|
91
|
-
lib/phronomy/agent_purged_error.rb
|
|
90
|
+
lib/phronomy/agent/lifecycle_contract/agent_already_exists_error.rb
|
|
91
|
+
lib/phronomy/agent/lifecycle_contract/agent_purged_error.rb
|
|
92
92
|
lib/phronomy/engine/runtime/agent_ownership_registry.rb
|
|
93
93
|
lib/phronomy/agent/agent_root.rb
|
|
94
|
-
lib/phronomy/agent/llm_input_build_context.rb
|
|
94
|
+
lib/phronomy/agent/context_contract/llm_input_build_context.rb
|
|
95
95
|
lib/phronomy/agent/shared_state.rb
|
|
96
96
|
spec/phronomy/agent/base_spec.rb
|
|
97
97
|
spec/phronomy/agent_spec.rb
|
|
@@ -119,9 +119,9 @@ done
|
|
|
119
119
|
|
|
120
120
|
syntax_files=(
|
|
121
121
|
spec/phronomy/architecture_governance_spec.rb
|
|
122
|
-
lib/phronomy/workflow.rb
|
|
123
|
-
lib/phronomy/workflow_context.rb
|
|
124
|
-
lib/phronomy/workflow_runner.rb
|
|
122
|
+
lib/phronomy/workflow/execution/workflow.rb
|
|
123
|
+
lib/phronomy/workflow/execution/workflow_context.rb
|
|
124
|
+
lib/phronomy/workflow/execution/workflow_runner.rb
|
|
125
125
|
lib/phronomy/engine/event_loop.rb
|
|
126
126
|
lib/phronomy/engine/fsm_session.rb
|
|
127
127
|
lib/phronomy/persistence/in_memory.rb
|
|
@@ -135,16 +135,16 @@ syntax_files=(
|
|
|
135
135
|
spec/phronomy/persistence/initial_format_migration_spec.rb
|
|
136
136
|
lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb
|
|
137
137
|
spec/phronomy/workflow_identity_contract_spec.rb
|
|
138
|
-
lib/phronomy/invocation_context.rb
|
|
138
|
+
lib/phronomy/engine/invocation_context.rb
|
|
139
139
|
lib/phronomy/agent/async_event_api.rb
|
|
140
140
|
lib/phronomy/agent/execution_coordinator.rb
|
|
141
141
|
lib/phronomy/agent/journal_record.rb
|
|
142
142
|
lib/phronomy/agent/context_assembler.rb
|
|
143
|
-
lib/phronomy/agent/context_policy.rb
|
|
144
|
-
lib/phronomy/agent/context_policy_input.rb
|
|
143
|
+
lib/phronomy/agent/context_contract/context_policy.rb
|
|
144
|
+
lib/phronomy/agent/context_contract/context_policy_input.rb
|
|
145
145
|
lib/phronomy/agent/context_policy_input_builder.rb
|
|
146
|
-
lib/phronomy/agent/context_plan.rb
|
|
147
|
-
lib/phronomy/agent/context_plan_validator.rb
|
|
146
|
+
lib/phronomy/agent/context_contract/context_plan.rb
|
|
147
|
+
lib/phronomy/agent/context_contract/context_plan_validator.rb
|
|
148
148
|
lib/phronomy/agent/context_policies/default.rb
|
|
149
149
|
spec/phronomy/agent/context_policy_architecture_regression_spec.rb
|
|
150
150
|
lib/phronomy/agent/agent_invocation.rb
|
|
@@ -177,7 +177,7 @@ syntax_files=(
|
|
|
177
177
|
spec/phronomy/workflow/admission_spec.rb
|
|
178
178
|
spec/phronomy/workflow/live_signal_spec.rb
|
|
179
179
|
spec/phronomy/workflow/fsm_session_spec.rb
|
|
180
|
-
lib/phronomy/generator_verifier.rb
|
|
180
|
+
lib/phronomy/generation/generator_verifier.rb
|
|
181
181
|
spec/phronomy/generator_verifier_spec.rb
|
|
182
182
|
spec/integration/subgraph_parallel_agent_tool_spec.rb
|
|
183
183
|
spec/phronomy/guarantee_model_spec.rb
|
|
@@ -197,11 +197,11 @@ syntax_files=(
|
|
|
197
197
|
spec/phronomy/fault_injection_advanced_spec.rb
|
|
198
198
|
spec/phronomy/persistence_architecture_regression_spec.rb
|
|
199
199
|
lib/phronomy/agent/base.rb
|
|
200
|
-
lib/phronomy/agent_already_exists_error.rb
|
|
201
|
-
lib/phronomy/agent_purged_error.rb
|
|
200
|
+
lib/phronomy/agent/lifecycle_contract/agent_already_exists_error.rb
|
|
201
|
+
lib/phronomy/agent/lifecycle_contract/agent_purged_error.rb
|
|
202
202
|
lib/phronomy/engine/runtime/agent_ownership_registry.rb
|
|
203
203
|
lib/phronomy/agent/agent_root.rb
|
|
204
|
-
lib/phronomy/agent/llm_input_build_context.rb
|
|
204
|
+
lib/phronomy/agent/context_contract/llm_input_build_context.rb
|
|
205
205
|
lib/phronomy/agent/shared_state.rb
|
|
206
206
|
lib/phronomy/agent/concerns/before_llm_input.rb
|
|
207
207
|
lib/phronomy/testing/persistence_contract/an_agent_repository.rb
|
|
@@ -322,7 +322,7 @@ bundle exec rspec \
|
|
|
322
322
|
spec/integration/multi_agent_handoff_followup_spec.rb
|
|
323
323
|
|
|
324
324
|
echo "== ACS-06 / CG-07 durable format / record-oriented Persistence SPI =="
|
|
325
|
-
ruby -c lib/phronomy/persistence.rb >/dev/null
|
|
325
|
+
ruby -c lib/phronomy/persistence/api/persistence.rb >/dev/null
|
|
326
326
|
ruby -c lib/phronomy/persistence/durable_record.rb >/dev/null
|
|
327
327
|
ruby -c lib/phronomy/persistence/durable_codec.rb >/dev/null
|
|
328
328
|
ruby -c lib/phronomy/persistence/repository_facades.rb >/dev/null
|
|
@@ -467,7 +467,7 @@ for rel in [
|
|
|
467
467
|
if fsm_new_has_id_kwarg(text):
|
|
468
468
|
raise SystemExit(f"FAIL: {rel} still injects a domain/context ID as FSMSession id")
|
|
469
469
|
|
|
470
|
-
workflow = pathlib.Path("lib/phronomy/workflow_runner.rb").read_text()
|
|
470
|
+
workflow = pathlib.Path("lib/phronomy/workflow/execution/workflow_runner.rb").read_text()
|
|
471
471
|
event_loop = pathlib.Path("lib/phronomy/engine/event_loop.rb").read_text()
|
|
472
472
|
fsm = pathlib.Path("lib/phronomy/engine/fsm_session.rb").read_text()
|
|
473
473
|
|
|
@@ -487,7 +487,7 @@ for required in ["workflow_terminal_persistence_result", ":persisting_terminal",
|
|
|
487
487
|
PY
|
|
488
488
|
|
|
489
489
|
echo "== ACS-13 Workflow admission / durable terminal barrier =="
|
|
490
|
-
ruby -c lib/phronomy/workflow_runner.rb >/dev/null
|
|
490
|
+
ruby -c lib/phronomy/workflow/execution/workflow_runner.rb >/dev/null
|
|
491
491
|
ruby -c lib/phronomy/engine/event_loop.rb >/dev/null
|
|
492
492
|
ruby -c lib/phronomy/engine/fsm_session.rb >/dev/null
|
|
493
493
|
ruby -c spec/phronomy/workflow/admission_spec.rb >/dev/null
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
# Measures the per-invoke cost of the Phronomy::Agent::Base framework path
|
|
6
6
|
# (context assembly, filter checks, before_llm_input hooks, response handling)
|
|
7
7
|
# with a fully stubbed LLM. No network calls are made.
|
|
8
|
+
# Each sample invokes a fresh Agent once. Agent construction is outside the
|
|
9
|
+
# measured block; growing conversation history is a different workload.
|
|
8
10
|
#
|
|
9
11
|
# Scenarios:
|
|
10
12
|
# 1. Minimal agent (no tools, no persistent Knowledge) — baseline framework overhead.
|
|
11
13
|
# 2. Tool-aware agent with a registered stub Tool.
|
|
12
|
-
# 3. Agent#stream setup latency (first-chunk time with stubbed stream).
|
|
13
14
|
|
|
14
15
|
require "benchmark"
|
|
15
16
|
require_relative "../lib/phronomy"
|
|
@@ -18,10 +19,12 @@ require_relative "../lib/phronomy"
|
|
|
18
19
|
# Shared stubs
|
|
19
20
|
# ---------------------------------------------------------------------------
|
|
20
21
|
|
|
21
|
-
BenchAgentMessage
|
|
22
|
+
module BenchAgentMessage
|
|
22
23
|
def self.assistant(content = "done")
|
|
23
|
-
new(
|
|
24
|
-
|
|
24
|
+
RubyLLM::Message.new(
|
|
25
|
+
role: :assistant, content: content,
|
|
26
|
+
tokens: RubyLLM::Tokens.new(input: 5, output: 5, cache_read: 0, cache_write: 0)
|
|
27
|
+
)
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
|
|
@@ -34,22 +37,25 @@ class BenchStubChat
|
|
|
34
37
|
@messages = []
|
|
35
38
|
end
|
|
36
39
|
|
|
37
|
-
def with_instructions(_) = self
|
|
38
|
-
def
|
|
40
|
+
def with_instructions(_, **_options) = self
|
|
41
|
+
def with_tools(*) = self
|
|
39
42
|
def with_temperature(_) = self
|
|
40
43
|
def with_cache_instructions(_) = self
|
|
41
44
|
def with_output_schema(_) = self
|
|
42
|
-
def on_tool_call(&) = self
|
|
43
|
-
def before_tool_call(&) = self
|
|
44
45
|
def last_message = @response
|
|
45
46
|
|
|
47
|
+
def after_message(&block)
|
|
48
|
+
@after_message = block
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
def ask(_)
|
|
47
|
-
|
|
48
|
-
@response
|
|
53
|
+
complete
|
|
49
54
|
end
|
|
50
55
|
|
|
51
|
-
def
|
|
52
|
-
|
|
56
|
+
def complete
|
|
57
|
+
@messages << @response
|
|
58
|
+
@after_message&.call(@response)
|
|
53
59
|
@response
|
|
54
60
|
end
|
|
55
61
|
end
|
|
@@ -69,7 +75,6 @@ end
|
|
|
69
75
|
# ---------------------------------------------------------------------------
|
|
70
76
|
|
|
71
77
|
BENCH_RESP = BenchAgentMessage.assistant("benchmark complete")
|
|
72
|
-
BENCH_RESP_CHAT = BenchStubChat.new(BENCH_RESP)
|
|
73
78
|
|
|
74
79
|
bench_minimal_class = Class.new(Phronomy::Agent::Base) do
|
|
75
80
|
agent_definition id: "bench-minimal", version: 1
|
|
@@ -86,22 +91,21 @@ bench_tool_class = Class.new(Phronomy::Agent::Base) do
|
|
|
86
91
|
define_method(:build_chat) { |*| BenchStubChat.new(BENCH_RESP) }
|
|
87
92
|
end
|
|
88
93
|
|
|
89
|
-
BENCH_AGENT_MINIMAL = bench_minimal_class.new
|
|
90
|
-
BENCH_AGENT_TOOLS = bench_tool_class.new
|
|
91
|
-
|
|
92
94
|
AGENT_INVOKE_ITERATIONS = 200
|
|
95
|
+
BENCH_AGENTS_MINIMAL = Array.new(AGENT_INVOKE_ITERATIONS) { bench_minimal_class.new }.freeze
|
|
96
|
+
BENCH_AGENTS_TOOLS = Array.new(AGENT_INVOKE_ITERATIONS) { bench_tool_class.new }.freeze
|
|
93
97
|
|
|
94
98
|
puts "=== bench_agent_invoke ==="
|
|
95
99
|
Benchmark.bm(50) do |x|
|
|
96
|
-
x.report("Agent#invoke —
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
x.report("Agent#invoke — fresh, no tools, #{AGENT_INVOKE_ITERATIONS} iters") do
|
|
101
|
+
BENCH_AGENTS_MINIMAL.each do |agent|
|
|
102
|
+
agent.invoke("ping")
|
|
99
103
|
end
|
|
100
104
|
end
|
|
101
105
|
|
|
102
|
-
x.report("Agent#invoke — tool-aware, #{AGENT_INVOKE_ITERATIONS} iters") do
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
x.report("Agent#invoke — fresh, tool-aware, #{AGENT_INVOKE_ITERATIONS} iters") do
|
|
107
|
+
BENCH_AGENTS_TOOLS.each do |agent|
|
|
108
|
+
agent.invoke("ping")
|
|
105
109
|
end
|
|
106
110
|
end
|
|
107
111
|
end
|
|
@@ -43,19 +43,18 @@ module BenchContextAssembler
|
|
|
43
43
|
call_sequence: 2, call_mode: :complete,
|
|
44
44
|
instruction: [], knowledge: knowledge, tools: [], conversation: conversation,
|
|
45
45
|
token_budget: Phronomy::LlmContextWindow::TokenBudget.new(
|
|
46
|
-
|
|
47
|
-
max_output_tokens: 512
|
|
46
|
+
max_input_tokens: [item_count * 16, 4_096].max
|
|
48
47
|
),
|
|
49
48
|
model_config: {}, previous_manifest: nil, metadata: {}
|
|
50
49
|
)
|
|
51
50
|
end
|
|
52
51
|
|
|
53
52
|
def assembler_fixture
|
|
54
|
-
persistence = Phronomy::Persistence
|
|
53
|
+
persistence = Phronomy::Persistence.in_memory
|
|
55
54
|
agent_class = Class.new(Phronomy::Agent::Base) do
|
|
56
55
|
agent_definition id: "bench-manifest-context-assembler", version: 1
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
# Resolve capabilities from RubyLLM's bundled registry; no provider call.
|
|
57
|
+
model "gpt-4o-mini"
|
|
59
58
|
max_output_tokens 1_024
|
|
60
59
|
instructions "Benchmark instruction"
|
|
61
60
|
end
|
|
@@ -102,7 +102,7 @@ stub_agent_class = Class.new(Phronomy::Agent::Base) do
|
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
define_method(:invoke_async) do |input, **_kw|
|
|
105
|
-
task = Phronomy::
|
|
105
|
+
task = Phronomy::TaskResult.deferred(name: "bench-stub")
|
|
106
106
|
begin
|
|
107
107
|
task.complete(invoke(input))
|
|
108
108
|
rescue => error
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Agent Chat and explicit state ownership (R09, second slice)
|
|
2
|
+
|
|
3
|
+
## Purpose and clients
|
|
4
|
+
|
|
5
|
+
Agent::Base is the declaration and lifecycle facade used by application Agent
|
|
6
|
+
subclasses. It also supplies internal hooks to normal execution, follow-up LLM
|
|
7
|
+
calls and recovery. Those callers need a Chat built from the selected or saved
|
|
8
|
+
model settings and populated with an already materialized projection. They do
|
|
9
|
+
not ask the Chat constructor to make Context Policy decisions again.
|
|
10
|
+
|
|
11
|
+
Applications create Agents and explicitly add knowledge, clear context/history,
|
|
12
|
+
reset context or close an idle Agent through Base. These operations append
|
|
13
|
+
Journal records and advance an AgentRoot together. The existing live root is
|
|
14
|
+
authoritative; an operation must not silently reload a newer root and retry.
|
|
15
|
+
|
|
16
|
+
Refactor 42 extracted ToolBinding and documented existing declaration rules.
|
|
17
|
+
Refactor 43 separates the remaining Chat construction and explicit state writes
|
|
18
|
+
while keeping the Base facade and live-state publication boundary.
|
|
19
|
+
|
|
20
|
+
## Ownership and placement
|
|
21
|
+
|
|
22
|
+
| Owner | Responsibility |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Base | Public declarations and lifecycle entry points, live-owner checks, selected class settings, operation-specific root changes, projection installation and publication of successful state writes. |
|
|
25
|
+
| RuntimeChatBuilder | RubyLLM Chat options and setters; provider-specific instruction cache representation. |
|
|
26
|
+
| StateWriter | Initial root/context/knowledge persistence and explicit idle-Agent Journal/root changes in one transaction. |
|
|
27
|
+
| ContextImporter / JournalRecord / AgentRoot | Existing history validation, record meanings and immutable root values. |
|
|
28
|
+
| ToolBinding / Orchestrator | Existing Tool decoration and invocation-specific subagent context. |
|
|
29
|
+
| ExecutionCoordinator and its workers | Existing execution-time writes and EventLoop-side publication, unchanged here. |
|
|
30
|
+
|
|
31
|
+
RuntimeChatBuilder and StateWriter live in agent/context_assembly, whose existing
|
|
32
|
+
collaborators already turn context inputs into runtime or durable records.
|
|
33
|
+
StateWriter is orchestration over ContextImporter, JournalRecord and AgentRoot;
|
|
34
|
+
it is not a low-level lifecycle primitive or a raw storage adapter. Placing it
|
|
35
|
+
in lifecycle would introduce lifecycle -> context_assembly and enlarge the
|
|
36
|
+
existing directory cycle. That placement was rejected during design validation.
|
|
37
|
+
No new directory, loader rule, mixin or namespace alias is needed.
|
|
38
|
+
|
|
39
|
+
There are two new internal collaborator classes, plus StateWriter's private
|
|
40
|
+
Update data value containing root and appended records. Neither collaborator
|
|
41
|
+
holds an Agent reference or invokes private Agent methods through send. The
|
|
42
|
+
mutation block passed to StateWriter is the existing operation-specific root
|
|
43
|
+
proposal, called at the same point inside the transaction.
|
|
44
|
+
|
|
45
|
+
## Chat construction and installation
|
|
46
|
+
|
|
47
|
+
Base#build_chat selects its default model/provider/temperature/token settings
|
|
48
|
+
only when model_config is falsey. An explicit empty Hash remains an explicit
|
|
49
|
+
config. RuntimeChatBuilder then builds options, creates RubyLLM.chat, applies
|
|
50
|
+
temperature, optionally applies max_output_tokens and returns the original
|
|
51
|
+
Chat, irrespective of setter return values. Zero remains a valid setting.
|
|
52
|
+
|
|
53
|
+
Base#apply_instructions keeps its signature and delegates the provider detail.
|
|
54
|
+
Only a truthy cache flag with provider.to_s == "anthropic" wraps instructions
|
|
55
|
+
in Anthropic::Content(cache: true). All other values pass through unchanged;
|
|
56
|
+
the with_instructions return value is retained.
|
|
57
|
+
|
|
58
|
+
Base#_apply_runtime_projection_to_chat remains a short orchestration hook. It
|
|
59
|
+
installs system instructions, prepares and installs each Tool in order, then
|
|
60
|
+
appends the original message objects to the existing Chat messages. Keeping the
|
|
61
|
+
hook retains application/test overrides of apply_instructions and Orchestrator's
|
|
62
|
+
prepare_tool_class(invocation:) cooperation. Moving it into a builder receiving
|
|
63
|
+
the entire Agent would merely introduce callbacks back into Base.
|
|
64
|
+
|
|
65
|
+
AgentInvocationSessionBuilder and InvocationRestorer keep using the same hooks.
|
|
66
|
+
Saved config is authoritative during recovery; current class declarations do
|
|
67
|
+
not overwrite it. A failure stops installation at that operation, propagates
|
|
68
|
+
the same error and does not install later Tools/messages. No new Chat cache,
|
|
69
|
+
provider-independent SPI, LLM call or Tool execution path is introduced.
|
|
70
|
+
|
|
71
|
+
## Initial persistence
|
|
72
|
+
|
|
73
|
+
Base resolves the Agent definition before calling StateWriter#create_root.
|
|
74
|
+
StateWriter constructs the initial root, then performs the existing sequence:
|
|
75
|
+
|
|
76
|
+
1. Create the root in the transaction.
|
|
77
|
+
2. Import/encode context records, followed by knowledge records, in order.
|
|
78
|
+
3. If records exist, append them at position zero, advance both revisions to
|
|
79
|
+
one and save the root with expected_revision zero.
|
|
80
|
+
4. Return the resulting root after the transaction call returns successfully.
|
|
81
|
+
|
|
82
|
+
Empty initial input does not append or advance revisions. String coercion of
|
|
83
|
+
knowledge, metadata normalization, imported text/JSON handling and invalid-format
|
|
84
|
+
errors remain unchanged. Base's initialize_owned_state still assigns the root,
|
|
85
|
+
reads the committed Journal and freezes its local record array. Hydration and
|
|
86
|
+
definition compatibility checks remain unchanged in Base.
|
|
87
|
+
|
|
88
|
+
## Explicit mutation and publication
|
|
89
|
+
|
|
90
|
+
For add_knowledge and context/lifecycle changes, Base first checks live ownership
|
|
91
|
+
and captures agent_root. StateWriter takes that root, persistence and agent ID
|
|
92
|
+
explicitly. Each operation retains this transaction sequence:
|
|
93
|
+
|
|
94
|
+
1. Assert durable execution idleness.
|
|
95
|
+
2. Construct the content/state record and append with the captured Journal head.
|
|
96
|
+
3. Build the next root; a context mutation's proposal block runs after append.
|
|
97
|
+
4. Save with the captured expected Agent revision.
|
|
98
|
+
5. After the transaction call returns, return Update(root, appended records).
|
|
99
|
+
|
|
100
|
+
Base applies the returned Journal records before replacing @root. StateWriter
|
|
101
|
+
never publishes live state and never reloads the mutable root or Journal.
|
|
102
|
+
add_knowledge still returns self; clear/reset/close still return the new root.
|
|
103
|
+
close! increments Agent revision while preserving context revision. Context
|
|
104
|
+
changes preserve the old generation in the event and the existing revision
|
|
105
|
+
fallback rule in the resulting root.
|
|
106
|
+
|
|
107
|
+
Block, content, append, CAS and commit failures escape without publication.
|
|
108
|
+
Failures inside a supported transaction roll back its durable writes. An error
|
|
109
|
+
is not wrapped, retried or turned into a false successful return. The transaction
|
|
110
|
+
method's own return value is ignored as before.
|
|
111
|
+
|
|
112
|
+
This is not a stronger transaction or concurrency contract. If a backend commits
|
|
113
|
+
then reports an unknown outcome, or local Journal publication fails after a
|
|
114
|
+
successful commit, durable and live state can differ just as before. There is
|
|
115
|
+
no new F1 reconciliation for these manual operations. If an application encloses
|
|
116
|
+
an Agent mutation in an outer Persistence transaction, returning from the inner
|
|
117
|
+
scope is not proof of the outer commit; this refactor adds no deferred-publication
|
|
118
|
+
or outer-rollback coordination. Application-owned outer transactions need a
|
|
119
|
+
separate design decision, not an implicit guarantee from this extraction.
|
|
120
|
+
|
|
121
|
+
The public lifecycle checks, purge ownership protocol, admission, hydration,
|
|
122
|
+
execution commits, SQL and stored formats are unchanged. Relocated private
|
|
123
|
+
record-building helpers are not retained as an extension API. Retained Chat,
|
|
124
|
+
Tool and root-proposal hooks keep their names and signatures.
|
|
125
|
+
|
|
126
|
+
## Validation and completion rule
|
|
127
|
+
|
|
128
|
+
Thirty-seven additional behavioral examples run through Base against both the
|
|
129
|
+
unchanged Refactor 42 and this candidate. They cover saved/default/empty config,
|
|
130
|
+
provider options, setter and hook ordering, original objects/errors, import
|
|
131
|
+
formats, atomic rollback, idle checks, event/revision rules and publication.
|
|
132
|
+
The existing architecture guard now checks StateWriter as well as Base for
|
|
133
|
+
forbidden mutable-root/Journal reload and live-state publication paths.
|
|
134
|
+
|
|
135
|
+
Full core/integration/examples, real SQLite, public API/SPI, RBS, style, isolated
|
|
136
|
+
gem loading and independent package application are recorded in the release
|
|
137
|
+
evidence. New private helpers are distinguished from the unchanged public
|
|
138
|
+
contract and retained hook signatures. Static dependency analysis rejects new
|
|
139
|
+
cycle membership rather than merely checking unchanged edge counts.
|
|
140
|
+
|
|
141
|
+
Refactor 43 is applied and verified at core 5c4c0392; R09 is closed. Its Tool
|
|
142
|
+
binding and declaration rules were already verified in Refactor 42. Base remains
|
|
143
|
+
the public facade; keeping short orchestration methods there is intentional.
|
|
144
|
+
The DSL behavior itself remains unchanged. R10 is implemented in Refactor 44,
|
|
145
|
+
pending application verification. The published SVG is applied43-01. See the
|
|
146
|
+
[naming boundary](entry-action-and-team-wording.md) and the separate
|
|
147
|
+
[open Tool schema finding](tool-schema-recording-gap.md).
|