phronomy 0.27.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 +52 -0
- data/CONTRIBUTING.md +8 -8
- data/README.md +9 -3
- data/benchmark/bench_agent_invoke.rb +25 -50
- data/benchmark/bench_context_assembler.rb +14 -11
- data/benchmark/bench_regression.rb +1 -1
- data/benchmark/bench_tool_schema.rb +1 -1
- data/docs/architecture/agent-chat-and-state-ownership.md +7 -1
- data/docs/architecture/agent-transition-ownership.md +13 -89
- data/docs/architecture/backend-groups.md +152 -0
- data/docs/architecture/before-llm-input.md +3 -3
- data/docs/architecture/context-management.md +1 -1
- 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 +6 -0
- data/docs/architecture/multi-agent-handoff.md +6 -5
- data/docs/architecture/persistence.md +27 -9
- 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 +10 -1
- data/docs/architecture/remaining-refactoring-plan.md +16 -0
- data/docs/architecture/storage-execution-boundaries.md +54 -0
- data/docs/architecture/tool-schema-recording-gap.md +6 -0
- data/docs/architecture/tracing.md +1 -1
- data/docs/architecture/workflow-terminal-ownership-design.md +2 -2
- data/docs/architecture.md +24 -11
- data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
- data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
- data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +2 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +2 -0
- data/docs/decisions/032-storage-backend-composition.md +5 -0
- data/docs/decisions/034-handoff-runner-coordination-ownership.md +2 -0
- data/docs/decisions/035-tool-executor-capability-ownership.md +1 -1
- data/docs/decisions/038-responsibility-based-source-layout.md +14 -0
- data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +8 -0
- data/docs/decisions/040-configuration-default-composition.md +12 -1
- data/docs/decisions/045-worker-input-restriction-ownership.md +4 -0
- data/docs/decisions/051-execution-outcome-worker-ownership.md +2 -0
- data/docs/decisions/056-workflow-terminal-policy-ownership.md +1 -1
- data/docs/decisions/058-neutral-storage-primitives.md +5 -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 +18 -1
- data/docs/execution-boundaries-preview.md +45 -0
- data/docs/features.md +8 -3
- data/docs/getting-started.md +9 -6
- data/docs/migrations/0.22.md +2 -2
- data/docs/migrations/durable-semantic-coordination-v2.md +2 -0
- data/docs/migrations/handoff-runner-multi-agent.md +2 -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/storage-async-client.md +103 -0
- data/docs/migrations/vector-async-clients.md +110 -0
- data/docs/persistence-backends.md +38 -21
- data/docs/runtime-and-concurrency.md +26 -1
- data/lib/phronomy/agent/admission.rb +78 -0
- data/lib/phronomy/agent/{lifecycle_contract/agent_already_exists_error.rb → agent_already_exists_error.rb} +1 -1
- data/lib/phronomy/agent/{lifecycle_contract/agent_busy_error.rb → agent_busy_error.rb} +1 -1
- data/lib/phronomy/agent/{lifecycle_contract/agent_purged_error.rb → agent_purged_error.rb} +1 -1
- data/lib/phronomy/{recovery → agent/api}/execution_rehydration_required_error.rb +1 -1
- data/lib/phronomy/agent/async_event_api.rb +37 -32
- data/lib/phronomy/agent/base.rb +74 -72
- data/lib/phronomy/agent/before_llm_input.rb +64 -0
- data/lib/phronomy/agent/composition/run_once.rb +1 -1
- data/lib/phronomy/agent/{context_assembly/context_candidate_resolver.rb → context_candidate_resolver.rb} +2 -2
- data/lib/phronomy/agent/{context_assembly/context_assembler.rb → context_preparation.rb} +35 -221
- data/lib/phronomy/agent/control_request.rb +21 -0
- data/lib/phronomy/agent/execution/agent_execution.rb +1 -1
- data/lib/phronomy/agent/execution/agent_invocation.rb +27 -53
- data/lib/phronomy/agent/execution/approval_resume_commit.rb +1 -1
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +17 -127
- data/lib/phronomy/agent/execution/exact_execution.rb +44 -23
- data/lib/phronomy/agent/execution/execution_cancellation.rb +8 -4
- data/lib/phronomy/agent/execution/execution_coordinator.rb +214 -395
- data/lib/phronomy/agent/execution/execution_metadata.rb +1 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +70 -126
- data/lib/phronomy/agent/execution/execution_registry.rb +6 -2
- data/lib/phronomy/agent/execution/execution_session_runner.rb +22 -27
- data/lib/phronomy/agent/execution/initial_preparation.rb +18 -116
- data/lib/phronomy/agent/execution/{agent_invocation_session_builder.rb → invocation_actions.rb} +54 -194
- data/lib/phronomy/agent/execution/invocation_transitions.rb +39 -1
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +7 -7
- 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/{handoff_context.rb → transfer_context.rb} +4 -4
- data/lib/phronomy/agent/handoff/{handoff_projection.rb → transfer_projection.rb} +14 -33
- data/lib/phronomy/{llm_contract/transport_error.rb → agent/handoff_error.rb} +1 -1
- data/lib/phronomy/agent/journal/journal_projection.rb +1 -1
- data/lib/phronomy/agent/knowledge_item.rb +13 -0
- data/lib/phronomy/agent/lifecycle/agent_root.rb +1 -1
- data/lib/phronomy/agent/lifecycle/ownership_registry.rb +18 -23
- data/lib/phronomy/agent/persistence/agent_repository.rb +29 -21
- data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
- data/lib/phronomy/agent/persistence/codec.rb +1 -21
- data/lib/phronomy/agent/persistence/execution_repository.rb +57 -41
- data/lib/phronomy/agent/persistence/journal_repository.rb +27 -18
- 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 +7 -2
- data/lib/phronomy/agent/persistence/watermark.rb +13 -11
- data/lib/phronomy/agent/recovery/invocation_restorer.rb +13 -21
- data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +10 -9
- data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +27 -27
- data/lib/phronomy/agent/recovery/recovery_coordinator/resolution.rb +19 -21
- data/lib/phronomy/agent/recovery/recovery_coordinator.rb +23 -16
- data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
- data/lib/phronomy/agent/recovery/recovery_support.rb +8 -11
- 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/{context_assembly/ruby_llm_materializer.rb → runtime_input.rb} +18 -35
- data/lib/phronomy/agent/{context_assembly/saved_context_reader.rb → saved_context_reader.rb} +6 -4
- data/lib/phronomy/agent/settings.rb +47 -0
- data/lib/phronomy/agent/{context_assembly/state_writer.rb → state_writer.rb} +4 -3
- data/lib/phronomy/agent/store.rb +253 -0
- data/lib/phronomy/agent/{lifecycle_contract/stream_callback_error.rb → stream_callback_error.rb} +1 -1
- data/lib/phronomy/agent/tool_execution/tool_binding.rb +4 -64
- data/lib/phronomy/agent/tool_execution/tool_invocation.rb +50 -219
- 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/configuration/runtime_settings.rb +49 -0
- data/lib/phronomy/content_store/storage_schema.rb +1 -0
- data/lib/phronomy/content_store/stored_contents.rb +2 -1
- data/lib/phronomy/context/assembly.rb +202 -0
- data/lib/phronomy/{llm_contract/context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +3 -1
- data/lib/phronomy/context/candidate.rb +51 -0
- data/lib/phronomy/context/constraint.rb +47 -0
- data/lib/phronomy/{agent/context_contract → context}/context_plan.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/context_plan_validator.rb +3 -3
- data/lib/phronomy/{agent/context_contract → context}/context_policy.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/context_policy_input.rb +1 -1
- data/lib/phronomy/{agent/context_assembly → 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_contract → context}/llm_input_build_context.rb +1 -1
- data/lib/phronomy/{agent/context_contract → context}/llm_input_manifest.rb +19 -19
- data/lib/phronomy/{agent/context_contract → context}/llm_input_patch.rb +1 -1
- 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 +36 -21
- data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
- data/lib/phronomy/engine/diagnostics.rb +1 -1
- data/lib/phronomy/engine/event_loop.rb +7 -7
- 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 +1 -6
- data/lib/phronomy/engine/fsm_session.rb +3 -3
- data/lib/phronomy/engine/metrics.rb +16 -14
- data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
- data/lib/phronomy/engine/runtime.rb +25 -12
- data/lib/phronomy/engine/terminal_decision.rb +7 -0
- data/lib/phronomy/execution/async_operation.rb +41 -0
- data/lib/phronomy/{engine → execution}/blocking.rb +2 -2
- data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +1 -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/{engine → execution}/execution.rb +61 -27
- data/lib/phronomy/execution/execution_receiver.rb +78 -0
- data/lib/phronomy/execution/execution_scope_state.rb +35 -0
- data/lib/phronomy/{engine → execution}/invocation_context.rb +0 -15
- data/lib/phronomy/execution/invocation_controls.rb +73 -0
- data/lib/phronomy/execution/runnable.rb +24 -0
- data/lib/phronomy/{engine → execution}/task_result.rb +3 -3
- data/lib/phronomy/execution/wait_policy.rb +24 -0
- data/lib/phronomy/filter/{contract/filter_block_error.rb → filter_block_error.rb} +1 -1
- data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
- data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
- data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +2 -2
- data/lib/phronomy/generation/generator_verifier.rb +7 -7
- data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
- data/lib/phronomy/{llm_contract → llm_adapter}/authentication_error.rb +3 -1
- data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
- data/lib/phronomy/llm_adapter/base.rb +49 -68
- data/lib/phronomy/{llm_contract → llm_adapter}/context_length_error.rb +3 -1
- data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
- data/lib/phronomy/llm_adapter/message.rb +62 -0
- data/lib/phronomy/{llm_contract → llm_adapter}/rate_limit_error.rb +3 -1
- 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/multi_agent/admission_registry.rb +1 -8
- 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/handoff → multi_agent}/handoff.rb +2 -2
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_capability_factory.rb +21 -2
- data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_policy.rb +1 -1
- data/lib/phronomy/multi_agent/handoff_runner.rb +77 -100
- data/lib/phronomy/{agent/handoff → multi_agent}/handoff_state.rb +1 -1
- data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
- data/lib/phronomy/multi_agent/persistence/codec.rb +20 -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 +58 -42
- data/lib/phronomy/multi_agent/persistence/team_repository.rb +29 -21
- 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/multi_agent/shared_state.rb +2 -2
- data/lib/phronomy/multi_agent/store.rb +156 -0
- data/lib/phronomy/multi_agent/team_coordinator.rb +83 -74
- data/lib/phronomy/multi_agent/team_ownership_registry.rb +2 -12
- 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 +2 -2
- 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 +9 -4
- 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 +5 -1
- data/lib/phronomy/runtime_composition/configuration.rb +146 -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/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 +8 -2
- 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 +2 -2
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +6 -6
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +55 -52
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +3 -3
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +7 -7
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +11 -11
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +57 -51
- data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +23 -22
- 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_execution/tool_definition_set.rb → tool/definition_set.rb} +7 -8
- 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/tool/tool_executor.rb +58 -0
- 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/execution/workflow.rb +7 -7
- data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
- data/lib/phronomy/workflow/execution/workflow_context.rb +2 -2
- data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +27 -0
- data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +3 -5
- data/lib/phronomy/workflow/execution/workflow_runner.rb +58 -79
- data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
- data/lib/phronomy/workflow/persistence/state_repository.rb +28 -22
- 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/{execution → runtime_binding}/workflow_terminal_policy.rb +4 -4
- data/lib/phronomy.rb +57 -16
- data/scripts/api_snapshot.rb +35 -15
- 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 -138
- 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 +10 -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 +6 -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 +1 -99
- 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.rbs → storage/contracts.rbs} +2 -16
- data/sig/phronomy/tool.rbs +48 -4
- 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 +318 -117
- 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 -548
- data/lib/phronomy/agent/context/capability/tool_executor.rb +0 -62
- data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
- data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +0 -36
- data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +0 -22
- 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/phase_machine_builder.rb +0 -101
- data/lib/phronomy/agent/execution/provider_call_outcome.rb +0 -106
- data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +0 -15
- data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +0 -131
- data/lib/phronomy/agent/handoff/handoff_request.rb +0 -45
- data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +0 -7
- data/lib/phronomy/agent/persistence/handoff_state_repository.rb +0 -58
- data/lib/phronomy/agent/persistence/queries.rb +0 -61
- data/lib/phronomy/agent/selection/candidate.rb +0 -53
- data/lib/phronomy/agent/selection/constraint.rb +0 -49
- data/lib/phronomy/agent/tool_execution/tool_call_intercepted.rb +0 -29
- data/lib/phronomy/agent/tool_execution/tool_invocation_session_builder.rb +0 -276
- data/lib/phronomy/configuration/configuration.rb +0 -68
- data/lib/phronomy/configuration/global_configuration.rb +0 -26
- data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
- data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
- data/lib/phronomy/engine/execution_receiver.rb +0 -65
- data/lib/phronomy/engine/runnable.rb +0 -54
- data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
- data/lib/phronomy/llm_contract/token_usage.rb +0 -85
- data/lib/phronomy/multi_agent/persistence/queries.rb +0 -30
- data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +0 -15
- data/lib/phronomy/output_parser/contract/parse_error.rb +0 -7
- data/lib/phronomy/persistence/api/persistence.rb +0 -140
- data/lib/phronomy/persistence_composition/repositories.rb +0 -77
- data/lib/phronomy/recovery/recovery.rb +0 -186
- data/lib/phronomy/tool/contract/tool_error.rb +0 -7
- 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/storage_contract/workflow_storage_schema.rb +0 -9
- data/sig/phronomy/execution_receiver.rbs +0 -34
- data/sig/phronomy/llm_adapter.rbs +0 -11
- data/sig/phronomy/runtime.rbs +0 -76
- /data/lib/phronomy/agent/{context_assembly/context_importer.rb → context_importer.rb} +0 -0
- /data/lib/phronomy/{engine → execution}/backpressure_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/cancellation_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/concurrency/worker_input_restricted.rb +0 -0
- /data/lib/phronomy/{engine → execution}/event_loop_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/execution_cancellation_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/execution_timeout_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_entry_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_transition_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/invalid_async_workflow_action_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/pool_shutdown_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/recursion_limit_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/runtime_shutdown_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/runtime_shutdown_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/scheduler_reentrancy_error.rb +0 -0
- /data/lib/phronomy/{engine → execution}/timeout_error.rb +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# r8 unit17 migration
|
|
2
|
+
|
|
3
|
+
This core-only update requires no application or stored-data migration.
|
|
4
|
+
Continue using Phronomy.configure and the existing per-instance/per-invocation
|
|
5
|
+
options. Public names, defaults, policy validation, nil semantics, and explicit
|
|
6
|
+
option priority remain unchanged.
|
|
7
|
+
|
|
8
|
+
Agent and Workflow read their own option values instead of application
|
|
9
|
+
Configuration. MultiAgent uses its optional configured Store provider. Logging
|
|
10
|
+
uses RuntimeSettings. Authorization pool sizing moves into the execution
|
|
11
|
+
connection while Agent retains approval and timeout decisions.
|
|
12
|
+
|
|
13
|
+
There is no settings-change notification or automatic in-flight update. Existing
|
|
14
|
+
read timing is preserved, including scoped configuration restoration and reset.
|
|
15
|
+
Do not capture an internal settings object as a permanent replacement for the
|
|
16
|
+
current accessor, or depend on Configuration's private instance variables.
|
|
17
|
+
|
|
18
|
+
Private Agent ExecutionEnvironment implementations used by internal integrations
|
|
19
|
+
or tests must implement submit_authorization(timeout:, cancellation_token:, &block).
|
|
20
|
+
The default Engine connection submits the same authorization work with the same
|
|
21
|
+
pool name, resource defaults, overload behavior, and owning Runtime. Ordinary
|
|
22
|
+
Tool implementations and application code require no changes. Tests should set
|
|
23
|
+
configuration through its writers rather than intercepting an old facade getter.
|
|
24
|
+
|
|
25
|
+
Apply from unit16 commit `fb551e1a1a8334b2547ecad126dd9c152c1b0f8c` in a new
|
|
26
|
+
`refactor/r8-unit17` worktree using the package's checked applier. Follow the
|
|
27
|
+
existing shutdown/drain procedure when replacing running code. Examples remain
|
|
28
|
+
on their unit6 sources and are verified against this core through PHRONOMY_PATH.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# R8 unit18 migration
|
|
2
|
+
|
|
3
|
+
Apply to core at unit17 commit `26792401144118f03025952aa9ec849fb16b577f`.
|
|
4
|
+
No examples source changes, public API updates, schema migrations or data rewrites
|
|
5
|
+
are required. Existing cancellation records remain valid.
|
|
6
|
+
|
|
7
|
+
Exact-execution resume with a cancelled token now records the request in the
|
|
8
|
+
existing Agent ledger before continuing recovery/waiting. A recording failure is
|
|
9
|
+
returned to the caller. Unresolved children continue to require factual resolution
|
|
10
|
+
and the parent remains active; cancellation receipt does not claim completion.
|
|
11
|
+
|
|
12
|
+
Cancellation metadata on the execution and MultiAgent extension is a snapshot of
|
|
13
|
+
its last save. If cancellation is recorded after that save, the independent Agent
|
|
14
|
+
ledger preserves intent until the next recovery/change reflects it. Use the
|
|
15
|
+
existing Agent cancellation observation instead of assuming every stored
|
|
16
|
+
snapshot is immediately updated.
|
|
17
|
+
|
|
18
|
+
Keep the existing stop/drain procedure when replacing running processes. This
|
|
19
|
+
package does not establish new compatibility guarantees for workers already
|
|
20
|
+
running code from another version. Reverting this source change needs no data
|
|
21
|
+
rollback, but reintroduces the cancellation-loss race.
|
|
22
|
+
|
|
23
|
+
## Delivery correction package
|
|
24
|
+
|
|
25
|
+
The unit18 cancellation-delivery correction applies on top of
|
|
26
|
+
`a89f42e3805fb548bf9587c49e1ab226efd174db`. It removes the gap between the
|
|
27
|
+
recording and notification decisions in `ExactExecution` delivery. The existing
|
|
28
|
+
preparation/delivery recheck, cancellation ledger and error behavior remain.
|
|
29
|
+
There are no additional API, schema or examples changes.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# R8 unit19 migration
|
|
2
|
+
|
|
3
|
+
Apply to core at unit18 delivery-correction commit
|
|
4
|
+
`a6f370d34e90ca274ec45a6b69ad1db9cb003707`.
|
|
5
|
+
No examples source change, data migration or public invocation API change is
|
|
6
|
+
required. Engine-private shutdown operations and their RBS declarations change.
|
|
7
|
+
|
|
8
|
+
Runtime shutdown now reports incomplete cleanup when workers remain alive. Check
|
|
9
|
+
cleanup_complete? before declaring resources released. reset_runtime! continues
|
|
10
|
+
to reject replacement after incomplete cleanup. Do not bypass that guard or
|
|
11
|
+
assume a cancelled TaskResult means its synchronous worker has stopped.
|
|
12
|
+
|
|
13
|
+
The existing Runtime stop-phase deadline, computed from cancel_grace with its
|
|
14
|
+
existing minimum grace, now also bounds pool joins. It is shared across EventLoop
|
|
15
|
+
and all pools; the previous additional 30 seconds per worker no longer applies
|
|
16
|
+
to Runtime shutdown. timeout still controls the preceding drain phase. Choose
|
|
17
|
+
grace appropriate to existing work, and configure native I/O timeouts where
|
|
18
|
+
needed. No Thread#raise or hard worker termination is added.
|
|
19
|
+
|
|
20
|
+
Shutdown remains terminal and returns its cached result on subsequent calls,
|
|
21
|
+
including an incomplete result. This change does not add retry or resume of the
|
|
22
|
+
shutdown procedure. Pool requests racing past the closed resource registry are
|
|
23
|
+
rejected with PoolShutdownError; new calls rejected earlier by Runtime retain
|
|
24
|
+
RuntimeShutdownError.
|
|
25
|
+
|
|
26
|
+
Use the existing controlled process-replacement procedure. Reverting the source
|
|
27
|
+
change needs no data rollback, but restores the resource leak and false-completion
|
|
28
|
+
risks. Metrics.snapshot behavior is unchanged in this unit (E03 is deferred).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# R8 unit20 migration
|
|
2
|
+
|
|
3
|
+
Apply to unit19 core commit `07b78c90ef6072f66fecb04ea6891eda50493546`.
|
|
4
|
+
No examples source change or data migration is required.
|
|
5
|
+
|
|
6
|
+
Metrics.snapshot, Diagnostics.snapshot and Diagnostics.dump keep their arguments,
|
|
7
|
+
metric keys, numeric values and output format. They no longer initialize execution
|
|
8
|
+
resources and remain usable while the default Runtime is stopping or stopped.
|
|
9
|
+
|
|
10
|
+
Before resource initialization, the corresponding values are zero. In particular,
|
|
11
|
+
offload_pool_size is zero until the default pool exists. Previously a snapshot
|
|
12
|
+
created the pool and reported its configured capacity. Do not use monitoring as
|
|
13
|
+
an implicit warmup. Normal execution still initializes the resources it needs.
|
|
14
|
+
|
|
15
|
+
For an existing pool, offload_pool_size remains its configured capacity after
|
|
16
|
+
shutdown; use the shutdown result to assess cleanup, not this metric. Retained
|
|
17
|
+
counters remain readable until default Runtime reset. After reset, observations
|
|
18
|
+
return zero until new resources are initialized. Named pools are not aggregated,
|
|
19
|
+
and simultaneous consistency across independently sampled counters is not added.
|
|
20
|
+
|
|
21
|
+
Unit19 stopping deadlines, completion judgment and cached-result behavior remain
|
|
22
|
+
unchanged. No public invocation API or persistence format changes. Reverting this
|
|
23
|
+
unit needs no data rollback but restores observation-triggered initialization and
|
|
24
|
+
shutdown-time diagnostic errors.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# r8 unit21 migration
|
|
2
|
+
|
|
3
|
+
This core-only responsibility refactor requires no application or stored-data
|
|
4
|
+
migration. Continue using Phronomy.configure with tool_result_max_size, tracer
|
|
5
|
+
and trace_pii, and the existing per-Tool max_result_size option. Public defaults,
|
|
6
|
+
nil semantics, read timing, truncation and redaction behavior remain unchanged.
|
|
7
|
+
Application-configured filter order and repetition remain unchanged too.
|
|
8
|
+
|
|
9
|
+
Tool and Tracing now obtain their settings through their own internal value
|
|
10
|
+
containers. Context::Assembly obtains its default tracer from Tracing while
|
|
11
|
+
retaining explicit injection and constructor-time selection. Composition still
|
|
12
|
+
selects concrete defaults and supplies current values; no manual per-operation
|
|
13
|
+
injection or settings-change subscription is required.
|
|
14
|
+
|
|
15
|
+
Internal tests or unsupported integrations constructing RuntimeSettings must
|
|
16
|
+
stop passing tracer: to its constructor or reading tracer, trace_pii and
|
|
17
|
+
tool_result_max_size from it. Ordinary application code should use the unchanged
|
|
18
|
+
public Configuration accessors. Its private instance variables and the new
|
|
19
|
+
domain settings containers are not an application extension API.
|
|
20
|
+
|
|
21
|
+
Apply from unit20 commit `bda5da03da5a4da33041953cf0eebaa32de7bb81` in a new
|
|
22
|
+
`refactor/r8-unit21` worktree using the package's checked applier. Verify the
|
|
23
|
+
expected tree before and after committing. Follow the existing shutdown/drain
|
|
24
|
+
procedure when replacing running code. Examples remain on their unit6 sources
|
|
25
|
+
and are verified against this core through PHRONOMY_PATH.
|
|
26
|
+
|
|
27
|
+
No data rollback is needed. Reverting this commit restores the earlier settings
|
|
28
|
+
ownership; it does not remove the unit19/20 Engine corrections.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# r8 unit22 migration
|
|
2
|
+
|
|
3
|
+
No application source or stored-data migration is required. Apply this core-only
|
|
4
|
+
package on unit21 commit `4525e71ca808acac9eb0302a59c32f00478a7782` and restart
|
|
5
|
+
using the application's existing drain/shutdown procedure.
|
|
6
|
+
|
|
7
|
+
- MCP public construction, execution, close, schema, authorization and result
|
|
8
|
+
formatting APIs are unchanged.
|
|
9
|
+
- A completed MCP call no longer retains a cancellation callback on a shared
|
|
10
|
+
caller token. A callback already taken by concurrent cancel! may still finish.
|
|
11
|
+
- Logical timeout does not end the SDK invocation's cancellation bridge. The
|
|
12
|
+
registration is released when that invocation exits.
|
|
13
|
+
- If Runtime rejects transport cleanup because it has stopped, the MCP caller
|
|
14
|
+
performs the existing synchronous close fallback and still receives the MCP
|
|
15
|
+
cancellation outcome. This can include the transport's normal close latency.
|
|
16
|
+
- Warning logging uses the same configured logger through neutral settings,
|
|
17
|
+
with stderr fallback when no logger is configured.
|
|
18
|
+
|
|
19
|
+
Execution, Engine and Contract source are unchanged. There are no new threads,
|
|
20
|
+
configuration options, timers or notification services. The existing MCP
|
|
21
|
+
cleanup pool remains in use while Runtime accepts work.
|
|
22
|
+
|
|
23
|
+
Custom tests that expected cancellation to reach an already-completed MCP call
|
|
24
|
+
should instead cancel while the SDK call is active and verify that completed
|
|
25
|
+
calls release their registrations. The SDK cancellation bridge helper is
|
|
26
|
+
private; its new subscriptions keyword is not a public application API.
|
|
27
|
+
|
|
28
|
+
Examples retain their unit6 source. Verify them against this core checkout using
|
|
29
|
+
PHRONOMY_PATH and restore only verification-generated lockfiles/artifacts.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# r8 unit23 migration
|
|
2
|
+
|
|
3
|
+
This is a core-only responsibility refactor on applied unit22.
|
|
4
|
+
|
|
5
|
+
- `Tools::Agent.from_agent`, synchronous `execute`, asynchronous `call_async`
|
|
6
|
+
and the public `Agent.run_once` API retain their signatures and behavior.
|
|
7
|
+
- Agent Tool calls still create a fresh Agent and ephemeral store. Configured
|
|
8
|
+
application stores do not replace this per-call store.
|
|
9
|
+
- `Testing::Eval::Scorer::LlmJudge` retains its constructor and scoring API.
|
|
10
|
+
Configure `llm_adapter` through the existing application configuration API.
|
|
11
|
+
- LlmJudge reads the default adapter for each score, after preparing its Request.
|
|
12
|
+
Existing scoped configuration and reset behavior are retained.
|
|
13
|
+
- The client factory is an internal boot binding. Applications do not need to
|
|
14
|
+
register it or adopt a new factory API.
|
|
15
|
+
- No Contract, Execution, Engine, RBS, data schema or stored-record migration is
|
|
16
|
+
required. Examples require verification only, with no source changes.
|
|
17
|
+
|
|
18
|
+
Use the package README to check the exact base commit, apply complete files,
|
|
19
|
+
verify the resulting tree, run the validation commands and commit the result.
|
|
20
|
+
Normal application loading remains `require "phronomy"`.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# r8 unit 4 migration
|
|
2
|
+
|
|
3
|
+
Update core and examples together. This is a refactoring-branch breaking change;
|
|
4
|
+
there are no compatibility aliases or automatic old-record loaders.
|
|
5
|
+
|
|
6
|
+
| Unit 3 | Unit 4 |
|
|
7
|
+
|---|---|
|
|
8
|
+
| `Agent::Handoff`, `Agent::HandoffPolicy` | `MultiAgent::Handoff`, `MultiAgent::HandoffPolicy` |
|
|
9
|
+
| `stores.team`, `config.team_store` | `stores.multi_agent`, `config.multi_agent_store` |
|
|
10
|
+
| HandoffRunner infers an Agent store | `HandoffRunner.new(main_agent:, handoffs:, persistence: stores.multi_agent)` |
|
|
11
|
+
| Orchestrator receives only Agent persistence | `Orchestrator.create(persistence: stores.agent, coordination_store: stores.multi_agent)`; pass both on `load` |
|
|
12
|
+
| Internal ExactExecution/metadata access by coordination | Agent reserved start, resume, cancellation and observation operations |
|
|
13
|
+
| AgentExecution / HandoffState envelope `0.1` | Envelope `0.2`; explicit offline conversion required |
|
|
14
|
+
| `coordination`, `multi_agent_coordination_ref`, Handoff result fields | immutable `reservation`, versioned `execution_extension`, `transfer_receipt` |
|
|
15
|
+
|
|
16
|
+
Construct one `PersistenceComposition.build(backend:)` and use its domain stores.
|
|
17
|
+
Ordinary Agents continue to use `persistence: stores.agent`. For custom
|
|
18
|
+
participants, follow `ExecutionChange`'s RBS contract and the
|
|
19
|
+
[transaction sequence](../architecture/r8-unit4.md). Do not serialize participant
|
|
20
|
+
objects, callbacks or live Agent references.
|
|
21
|
+
|
|
22
|
+
## Offline SQL conversion
|
|
23
|
+
|
|
24
|
+
Stop all writers before exporting, including background workers and other
|
|
25
|
+
processes. Keep the old database unchanged. Run commands from example 30 (SQLite)
|
|
26
|
+
or 31 (PostgreSQL), with `PHRONOMY_PATH` pointing to the unit 4 core. The source DB
|
|
27
|
+
must have the unit 3 schema. The destination must be a separate empty database.
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
export SOURCE_DATABASE_URL='sqlite3:/absolute/path/old.sqlite3'
|
|
31
|
+
export DESTINATION_DATABASE_URL='sqlite3:/absolute/path/new.sqlite3'
|
|
32
|
+
bundle exec ruby ../scripts/migrate_unit4.rb export source.json --quiescent
|
|
33
|
+
bundle exec ruby ../scripts/migrate_unit4.rb convert source.json converted.json --quiescent
|
|
34
|
+
bundle exec ruby ../scripts/migrate_unit4.rb import converted.json --quiescent
|
|
35
|
+
bundle exec ruby ../scripts/migrate_unit4.rb verify converted.json --quiescent
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use the corresponding PostgreSQL URLs with example 31. The importer creates the
|
|
39
|
+
new destination schema, including retention/cancellation tables, refuses populated
|
|
40
|
+
tables, and commits all resources together. It preserves record IDs, physical and
|
|
41
|
+
logical revisions, stream positions, result/error content, transfer provenance,
|
|
42
|
+
knowledge order and unresolved work. A content digest, reference, owner, revision
|
|
43
|
+
or format mismatch aborts conversion. A checksum binds the converted resource set
|
|
44
|
+
to its validation. Do not edit converted JSON manually.
|
|
45
|
+
|
|
46
|
+
Verification establishes a separate connection pool and compares the complete
|
|
47
|
+
exported destination with the converted snapshot. Before switching application
|
|
48
|
+
configuration, load representative Agents with their current definitions and
|
|
49
|
+
participant wiring, read completed results and resume only continuations whose
|
|
50
|
+
external outcomes are known. Unknown external operations remain unresolved; the
|
|
51
|
+
migration neither retries them nor declares them complete. Keep both exports and
|
|
52
|
+
the old DB until that operational validation is complete. Database cutover is
|
|
53
|
+
explicit and is never performed by the migration command.
|
|
54
|
+
|
|
55
|
+
For non-SQL backends, `Unit4Migration.convert(snapshot, quiescent: true)` is the
|
|
56
|
+
pure conversion boundary. Implement offline export/import of the documented
|
|
57
|
+
`phronomy.snapshot/1` resources using the backend's own driver. No live-code
|
|
58
|
+
fallback is supplied.
|
|
59
|
+
|
|
60
|
+
## Retention lifecycle
|
|
61
|
+
|
|
62
|
+
After all results in a conversation have been consumed, call
|
|
63
|
+
`runner.forget_history!` (or `stores.multi_agent.forget_handoff(main_id)`) before
|
|
64
|
+
purging retained participants. For completed durable subagent history use
|
|
65
|
+
`stores.multi_agent.forget_subagents(agent_id:, execution_id:)`. Active or
|
|
66
|
+
unresolved work rejects history deletion. These operations release their own
|
|
67
|
+
holds; they do not remove another conversation's references.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# r8 unit 5 API migration
|
|
2
|
+
|
|
3
|
+
Apply core and examples together. No saved Agent, MultiAgent or Workflow record
|
|
4
|
+
format changes in this unit. Old constants and forwarding aliases are removed.
|
|
5
|
+
|
|
6
|
+
| Previous API | Current API |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| `Phronomy::VectorStore::Embeddings::*` | `Phronomy::Embeddings::*` |
|
|
9
|
+
| `Phronomy::VectorStore::Loader::*` | `Phronomy::Documents::Loader::*` |
|
|
10
|
+
| `Phronomy::VectorStore::Splitter::*` | `Phronomy::Documents::Splitter::*` |
|
|
11
|
+
|
|
12
|
+
VectorStore callers continue using `add`, `search`, `remove`, `clear` and `size`.
|
|
13
|
+
Custom backends now override protected `perform_add`, `perform_search`,
|
|
14
|
+
`perform_remove`, `perform_clear`, `perform_size`, and optionally
|
|
15
|
+
`embedding_dimension`. The common Base performs input/result validation and
|
|
16
|
+
returns `self` for add/remove/clear; the return value from these three hooks is
|
|
17
|
+
ignored. See `sig/phronomy/vector_store/base.rbs` for exact arguments. RBS models
|
|
18
|
+
the non-public hooks as private because it cannot express Ruby protected visibility.
|
|
19
|
+
|
|
20
|
+
Custom embedding providers implement the protected hook, not the public template:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
class KeywordEmbeddings < Phronomy::Embeddings::Base
|
|
24
|
+
protected
|
|
25
|
+
|
|
26
|
+
def perform_embed(text, cancellation_token = nil)
|
|
27
|
+
# Common input/result validation and the initial cancellation checkpoint
|
|
28
|
+
# are inherited. Long-running implementations may check the signal again.
|
|
29
|
+
[text.scan(/refund/i).length.to_f, text.scan(/shipping/i).length.to_f]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
provider = KeywordEmbeddings.new
|
|
34
|
+
vector = provider.embed("refund")
|
|
35
|
+
task = Phronomy::Embeddings::AsyncClient.new(adapter: provider).embed_async("shipping")
|
|
36
|
+
result = task.wait_result
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Embedding input must be a String, including an optional empty string; output must
|
|
40
|
+
be a non-empty Array of finite real numbers. Provider output is copied to a Float
|
|
41
|
+
array. An empty or malformed vector raises `Embeddings::InvalidResultError`.
|
|
42
|
+
RubyLLM provider failures now raise `Embeddings::TransportError`; inspect `cause`
|
|
43
|
+
for provider-specific details. Application exceptions are unchanged.
|
|
44
|
+
|
|
45
|
+
Vector ids must be Strings and metadata must be a Hash. Numeric strings, NaN,
|
|
46
|
+
infinity and complex components are rejected before backend I/O. Zero-dimensional
|
|
47
|
+
vectors still work in InMemory. `k` accepts positive Integers or decimal strings,
|
|
48
|
+
including `"08"`; Float truncation, hexadecimal/octal interpretation, whitespace
|
|
49
|
+
and arbitrary `to_int` coercions are not part of the contract. Results must satisfy
|
|
50
|
+
the public shape, score ordering and limit. Invalid backend results raise
|
|
51
|
+
`VectorStore::InvalidResultError`; they are never retried automatically.
|
|
52
|
+
|
|
53
|
+
Update custom backend tests to exercise inherited public operations. Do not
|
|
54
|
+
silence malformed results, return a fake zero count on transport failure, or add
|
|
55
|
+
an old-name alias to bypass the migration. Real Pgvector and RedisSearch deployments
|
|
56
|
+
must run their actual-service conformance tests before rollout.
|
|
57
|
+
|
|
58
|
+
The revised unit 5 candidate also tightens concrete backend response decoding.
|
|
59
|
+
RedisSearch expects RESP2; a missing whole search reply, malformed field pairs,
|
|
60
|
+
invalid counts or non-numeric distances now fail with `InvalidResultError` rather
|
|
61
|
+
than becoming an empty result, zero count or similarity 1. Document contents that
|
|
62
|
+
Redis explicitly reports as null during expiration/update are still omitted.
|
|
63
|
+
The total match count may exceed the returned page; these valid cases are tested.
|
|
64
|
+
RESP3 is not introduced by this update.
|
|
65
|
+
|
|
66
|
+
For Pgvector, a NULL metadata column remains `{}`, while an empty string, invalid
|
|
67
|
+
JSON, or JSON that is not an object now fails. An already-decoded Hash and a JSON
|
|
68
|
+
object remain accepted. Redis missing/null metadata likewise remains `{}`.
|
|
69
|
+
Pgvector rejects malformed scores and ids; integer database ids are still mapped
|
|
70
|
+
to String. JSON parser errors are retained as `cause`. Connection errors remain
|
|
71
|
+
unchanged and are not retried.
|
|
72
|
+
|
|
73
|
+
Check pre-existing metadata for invalid JSON or non-object values before rollout;
|
|
74
|
+
do not silently replace corrupt values with `{}` to make verification pass.
|
|
75
|
+
These parsing rules are implemented by the respective backend, not by Base.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# r8 unit 6 migration
|
|
2
|
+
|
|
3
|
+
Apply core and examples together on the applied unit 5 baseline. There are no
|
|
4
|
+
compatibility aliases. Update custom adapters and code rescuing LLM failures.
|
|
5
|
+
|
|
6
|
+
| Previous API | Current API |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| `Phronomy::TokenUsage` | `Phronomy::LLMAdapter::TokenUsage` |
|
|
9
|
+
| `Phronomy::TransportError` | `Phronomy::LLMAdapter::TransportError` |
|
|
10
|
+
| `Phronomy::RateLimitError` | `Phronomy::LLMAdapter::RateLimitError` |
|
|
11
|
+
| `Phronomy::AuthenticationError` | `Phronomy::LLMAdapter::AuthenticationError` |
|
|
12
|
+
| `Phronomy::ContextLengthError` | `Phronomy::LLMAdapter::ContextLengthError` |
|
|
13
|
+
| Adapter `build_chat`, `configure_chat`, `message`, `tool_call` | Backend-owned private translation; removed from the extension SPI |
|
|
14
|
+
| Adapter `complete(chat, message, config:)` / `stream(...)` | Inherited `complete(request, cancellation_token:)` / `stream(...)` |
|
|
15
|
+
| SDK-shaped recovery provider result | `LLMAdapter::Response` or `Response#to_h` |
|
|
16
|
+
|
|
17
|
+
Implement protected hooks, leaving public validation/cancellation templates intact:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
class EchoBackend < Phronomy::LLMAdapter::Base
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def perform_complete(request, cancellation_token:)
|
|
24
|
+
Phronomy::LLMAdapter::Response.new(content: request.message || "continued")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def perform_stream(request, cancellation_token:)
|
|
28
|
+
result = perform_complete(request, cancellation_token: cancellation_token)
|
|
29
|
+
yield Phronomy::LLMAdapter::StreamChunk.new(content: result.content)
|
|
30
|
+
result
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
Phronomy.configure { |config| config.llm_adapter = EchoBackend.new }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Request contains JSON model_config, optional system/new message, immutable
|
|
37
|
+
Message history and inert Tool definition Hashes. `identity` and local
|
|
38
|
+
`input_budget` have defaults. Backend hooks return Response; stream yields
|
|
39
|
+
StreamChunk values. Tool requests are `Tool::CallRequest(id:, name:, arguments:,
|
|
40
|
+
metadata:)` values in an ordered array, with unique nonempty IDs. They never
|
|
41
|
+
contain executable Tools or approval decisions. Return assistant responses only.
|
|
42
|
+
Response/Message content is text, structured JSON or nil. Unknown token counts
|
|
43
|
+
are nil; explicit zero is zero. TokenUsage no longer provides SDK `from_tokens`.
|
|
44
|
+
|
|
45
|
+
Model/provider are nonempty Strings or nil, temperature a finite number or nil,
|
|
46
|
+
max_output_tokens a positive Integer or nil, and instruction-cache/model-existence
|
|
47
|
+
flags booleans or nil. The default RubyLLM backend still owns provider-specific
|
|
48
|
+
options and error translation. Existing provider/application errors are not
|
|
49
|
+
silently swallowed or converted into success. Custom synchronous hooks must
|
|
50
|
+
check cancellation during their own long operations where they can cooperate.
|
|
51
|
+
|
|
52
|
+
## Tool schemas and approval
|
|
53
|
+
|
|
54
|
+
Tool::Base owns `parameter`/`param`, `parameters`/`params`, declaration inheritance,
|
|
55
|
+
name/description, provider options, `validate_arguments`, `call`, and `call_async`.
|
|
56
|
+
It is not a RubyLLM::Tool. Incidental inherited SDK APIs such as approval_resolver,
|
|
57
|
+
split_result and SDK result/content classes are not part of the new Tool API.
|
|
58
|
+
Keep Agent approval policies on the Agent/Tool authorization contract.
|
|
59
|
+
|
|
60
|
+
`parameters` accepts an explicit object schema or Schematist DSL (the DSL retains
|
|
61
|
+
its syntax without loading RubyLLM). JSON Schema 2020-12 is the supported dialect,
|
|
62
|
+
implicit when `$schema` is absent. Root type must be object. Supported constraints
|
|
63
|
+
include required/extra properties, nested objects/arrays, enum/const, numbers,
|
|
64
|
+
strings/formats and combinators. Unknown keywords/formats, alternate dialects,
|
|
65
|
+
custom vocabularies, `$id`/anchors and external refs fail at declaration time.
|
|
66
|
+
Local `#` / `#/...` references are resolved at construction. `strict` is a provider
|
|
67
|
+
annotation, not a substitute for required/additionalProperties constraints.
|
|
68
|
+
Defaults are annotations and are not injected into arguments.
|
|
69
|
+
|
|
70
|
+
Legacy optional `param` declarations continue to accept explicit nil and now
|
|
71
|
+
advertise a nullable type (and nullable enum). A legacy optional nil is normalized
|
|
72
|
+
to omission before approval/execution, preserving Ruby keyword defaults. An
|
|
73
|
+
absent optional key is not injected. Explicit schemas accept null only when their own constraints allow it.
|
|
74
|
+
|
|
75
|
+
Every declaration path validates before execution. `:raise` raises ToolError;
|
|
76
|
+
`:return_error` returns the existing schema-error text; `:coerce` converts explicit
|
|
77
|
+
primitive property/item types and then validates every constraint. It does not
|
|
78
|
+
guess a branch or cast through references/combinators. Fractional values are not
|
|
79
|
+
truncated to integers. Validation snapshots input containers; it does not mutate
|
|
80
|
+
the caller's arguments. Top-level keys become keyword symbols. Extra keys with
|
|
81
|
+
no declared/inferred parameters are rejected rather than passed to execute.
|
|
82
|
+
|
|
83
|
+
Approval receives the validated/coerced snapshot. Execution reuses those values
|
|
84
|
+
and validates against the same published schema. `on_error` does not turn schema
|
|
85
|
+
errors into successful execution. Unqualified legacy array declarations now
|
|
86
|
+
advertise unconstrained JSON items, matching their actual validation rule; use
|
|
87
|
+
an explicit items schema to restrict them.
|
|
88
|
+
|
|
89
|
+
## Stored and in-flight executions
|
|
90
|
+
|
|
91
|
+
Storage SPI and SQL schemas are unchanged. New Tool batch metadata additionally
|
|
92
|
+
records `validated_arguments`, separately from the unchanged raw request fields.
|
|
93
|
+
Agent authorization projects and compares that exact snapshot (including explicit
|
|
94
|
+
null in explicit schemas). Older snapshots without this field use the historical
|
|
95
|
+
raw-argument/optional-nil-omission rule. Existing journal message boundaries,
|
|
96
|
+
Tool call identities and recorded usage remain readable. Legacy top-level
|
|
97
|
+
thought_signature is decoded into opaque CallRequest metadata and rendered by
|
|
98
|
+
the backend. Old SDK usage field spellings remain accepted by SavedContextReader.
|
|
99
|
+
No stored records are silently rewritten and no automatic migration is run.
|
|
100
|
+
|
|
101
|
+
Saved Tool definitions are compared exactly. Removing SDK-generated annotations,
|
|
102
|
+
correctly advertising nested required/extra-key rules or array item rules can
|
|
103
|
+
change the definition even when application source is unchanged. Finish or
|
|
104
|
+
explicitly resolve in-flight unit 5 executions on their original version before
|
|
105
|
+
upgrading. Quiescent Agent history remains readable. If a saved in-flight Tool
|
|
106
|
+
definition differs, recovery rejects it; do not remove that comparison or modify
|
|
107
|
+
historical manifests to force continuation. Saved invalid model configuration
|
|
108
|
+
also needs resolution on the original version. No new cross-version in-flight
|
|
109
|
+
compatibility guarantee is made.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Migrating to r8 unit 7
|
|
2
|
+
|
|
3
|
+
Apply after core b337fc77dae530269bc34d895365032873d544ad (r8 unit 6).
|
|
4
|
+
Public Agent invocation, streaming, approval, cancellation and recovery signatures
|
|
5
|
+
and persistence record schemas are unchanged. The current unit 6 examples need
|
|
6
|
+
no source changes. Run them against the candidate using PHRONOMY_PATH and the
|
|
7
|
+
correct BUNDLE_GEMFILE for each example directory.
|
|
8
|
+
|
|
9
|
+
There are no compatibility aliases for removed internal APIs:
|
|
10
|
+
|
|
11
|
+
| Internal use | Replacement |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| AgentInvocationSessionBuilder | AgentInvocation plus the owning ExecutionEnvironment.build_agent_session |
|
|
14
|
+
| AgentInvocationSessionBuilder entry/prepared actions | InvocationActions |
|
|
15
|
+
| ExecutionSessionRunner.new(runtime: ...) | ExecutionSessionRunner.new(environment: ...) |
|
|
16
|
+
| OwnershipRegistry.for/existing_for(Runtime) | Pass an ExecutionEnvironment; EngineEnvironment adapts Runtime |
|
|
17
|
+
| ExecutionReceiver subclasses initialize(event_loop:) | initialize(channel:), preserving super |
|
|
18
|
+
| AgentInvocation.begin_llm_call! implicit Runtime lookup | Explicit llm_call_id from durable prepared execution |
|
|
19
|
+
|
|
20
|
+
ExecutionEnvironment is a private framework connection, not an application
|
|
21
|
+
configuration feature. Do not serialize environments, channels, sessions or live
|
|
22
|
+
registries. The default composition is installed by requiring phronomy. State
|
|
23
|
+
policy loading alone does not install a runtime. Existing persisted Agent/Tool
|
|
24
|
+
identities, revisions, authorization snapshots and recovery classifications are
|
|
25
|
+
retained. This change does not add support for exchanging in-flight unit 5 or
|
|
26
|
+
older execution snapshots with unit 6/7 workers.
|
|
27
|
+
|
|
28
|
+
Stop/drain old processes using the existing deployment procedure before replacing
|
|
29
|
+
code. Deploy all internal call-site changes together. The application package
|
|
30
|
+
contains a strict-base dry-run/applier, expected-tree verification, review patch,
|
|
31
|
+
validation logs and rollback guidance. Run --verify before and after commit.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Migrating to r8 unit 8
|
|
2
|
+
|
|
3
|
+
Apply after core a601a0654ace42640f0251b129359ca1f326e3ad (unit 7).
|
|
4
|
+
This is a core-only change. The unit 6 examples at
|
|
5
|
+
ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
|
|
6
|
+
|
|
7
|
+
Public Agent invocation/stream/approval/cancellation/recovery signatures and
|
|
8
|
+
Tool#call_async(args, cancellation_token:, config:) are unchanged. Tool::Operation
|
|
9
|
+
adds an explicit C06 operation entry and result transformation API; application
|
|
10
|
+
Tools do not need to adopt it. The supplied submitter applies to the default
|
|
11
|
+
offloaded operation only. Custom async implementations retain their existing
|
|
12
|
+
execution mechanism and configuration.
|
|
13
|
+
|
|
14
|
+
| Internal use | Replacement |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| Agent::ToolInvocationSessionBuilder.build / build_for_resume | The owning ExecutionEnvironment.build_tool_session, with resume_event/resume_phase when needed |
|
|
17
|
+
| ToolInvocationSessionBuilder transition constants | Agent::ToolInvocationTransitions |
|
|
18
|
+
| ToolInvocationSessionBuilder entry operations | Agent::ToolInvocationActions |
|
|
19
|
+
| ToolInvocation.start_authorization/runtime: and start_execution/runtime: | Pass environment: explicitly; never reconstruct it from a new global Runtime |
|
|
20
|
+
| Tool::ToolExecutor.call_async(runtime:) | Tool::Operation.call_async(submitter:) for contract consumers; default executor takes submitter: internally |
|
|
21
|
+
| Agent ToolBinding's custom-async detection and mapping mechanism | Tool::Operation.with_result_transform; Agent retains filter configuration |
|
|
22
|
+
|
|
23
|
+
Removed internal names have no aliases. Deploy all internal call sites together.
|
|
24
|
+
Do not persist execution environments, submitters, FSM sessions or parent sinks.
|
|
25
|
+
Durable IDs, record schemas, revision checks and saved approval evidence are
|
|
26
|
+
unchanged. The change does not certify new in-flight cross-version compatibility.
|
|
27
|
+
Use the existing stop/drain procedure before replacing running processes.
|
|
28
|
+
|
|
29
|
+
The application ZIP contains strict-base --check/--apply/--verify commands,
|
|
30
|
+
complete replacement files and deletions, expected-tree verification, a review
|
|
31
|
+
patch, validation evidence and rollback instructions. Run --verify before and
|
|
32
|
+
after commit. Verify examples with PHRONOMY_PATH pointing at the candidate and
|
|
33
|
+
unset a stale BUNDLE_GEMFILE before entering each Bundler context.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# R8 unit 9 migration
|
|
2
|
+
|
|
3
|
+
Apply to core unit 8, commit e9f6cc16da19be82a0b7777486926ba46d070def.
|
|
4
|
+
Examples source remains at unit 6, ed455c52018338f7c5a4c2948ae0d7db131aa090.
|
|
5
|
+
|
|
6
|
+
No public Tool or Agent signature, stored schema, migration CLI or example source
|
|
7
|
+
change is required. Existing configured filter order and repeated registrations
|
|
8
|
+
are preserved. The correction removes only the extra transformation caused by
|
|
9
|
+
Base's standard async-to-sync delegation under a custom async result decorator.
|
|
10
|
+
|
|
11
|
+
A custom call_async using super now passes its raw delegated result through its
|
|
12
|
+
own processing before the async decorator applies the configured transform.
|
|
13
|
+
Code accidentally relying on the duplicate/intermediate transformation should
|
|
14
|
+
express the required stages explicitly in application filter configuration.
|
|
15
|
+
|
|
16
|
+
A custom call_async explicitly calling public call retains that call's filters;
|
|
17
|
+
the enclosing async result decorator also retains its stage. Do not substitute
|
|
18
|
+
call for super when the intent is to delegate to Base's normal async execution.
|
|
19
|
+
The framework does not suppress application-authored calls or infer their intent.
|
|
20
|
+
|
|
21
|
+
Private changes: Base uses Tool::Operation.synchronous_delegate; ToolExecutor
|
|
22
|
+
accepts a bound synchronous_call keyword. Applications should not use these
|
|
23
|
+
private bridge helpers. Custom async implementations retain their existing
|
|
24
|
+
execution mechanism and keyword protocol.
|
|
25
|
+
|
|
26
|
+
Use the normal process stop/drain and restart procedure. This unit does not add
|
|
27
|
+
cross-version in-flight compatibility or rollback of external Tool side effects.
|
|
28
|
+
See docs/architecture/r8-unit9.md for operation-boundary examples.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Storage asynchronous execution and ContentStore ownership
|
|
2
|
+
|
|
3
|
+
P4 adds the public Beta `Phronomy::Storage::AsyncClient`. Synchronous storage
|
|
4
|
+
backends and `Persistence#transaction` keep their existing interfaces. Backend
|
|
5
|
+
authors implement no scheduler or async methods.
|
|
6
|
+
|
|
7
|
+
## Public transaction API
|
|
8
|
+
|
|
9
|
+
Construct `Storage::AsyncClient.new(backend: raw_backend, pool: nil)` around a
|
|
10
|
+
Storage SPI 2 backend. For an existing Persistence facade, use
|
|
11
|
+
`persistence.backend`. The transaction block receives a **raw Storage::View**,
|
|
12
|
+
not the domain repositories yielded by `Persistence#transaction`.
|
|
13
|
+
|
|
14
|
+
`transaction_async(cancellation_token: nil, timeout: nil) { |view| ... }`
|
|
15
|
+
returns the pool's original TaskResult. The complete transaction runs on one
|
|
16
|
+
worker, using the backend's normal connection and scope. Do not split a
|
|
17
|
+
transaction across workers or wait for another TaskResult inside its block.
|
|
18
|
+
Explicit synchronous `backend.transaction` calls within the block retain nested
|
|
19
|
+
savepoint behavior.
|
|
20
|
+
|
|
21
|
+
### Complete offline example
|
|
22
|
+
|
|
23
|
+
This requires a checkout containing P4; the previously released 0.27.0 gem does
|
|
24
|
+
not contain the new client. It uses only the public raw storage contract.
|
|
25
|
+
|
|
26
|
+
```ruby runnable
|
|
27
|
+
require "phronomy"
|
|
28
|
+
require "json"
|
|
29
|
+
|
|
30
|
+
resource = Phronomy::Storage::Resource.new(id: "example.notes", kind: :records)
|
|
31
|
+
backend = Phronomy::Storage::Backends::InMemory.new(resources: [resource])
|
|
32
|
+
client = Phronomy::Storage::AsyncClient.new(backend: backend)
|
|
33
|
+
|
|
34
|
+
begin
|
|
35
|
+
record = Phronomy::Storage::DurableRecord.new(
|
|
36
|
+
record_type: "example.note", format_version: "0.1", payload: {"text" => "saved"}
|
|
37
|
+
)
|
|
38
|
+
task = client.transaction_async do |view|
|
|
39
|
+
rows = view.records(resource)
|
|
40
|
+
rows.insert(key: "note-1", revision: 1, attributes: {}, record: record)
|
|
41
|
+
rows.fetch("note-1").record.payload
|
|
42
|
+
end
|
|
43
|
+
puts JSON.generate(task.wait_result)
|
|
44
|
+
ensure
|
|
45
|
+
Phronomy.reset_runtime!
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The output is `{"text":"saved"}`. Return a value from the transaction. A bound
|
|
50
|
+
view or resource handle becomes invalid after the block finishes, even if it
|
|
51
|
+
was returned through TaskResult. Scope also rejects access from another thread.
|
|
52
|
+
Exceptions and invalid non-local block exits roll back through the existing
|
|
53
|
+
backend rules; no new transaction implementation is introduced.
|
|
54
|
+
|
|
55
|
+
## Admission, cancellation and ownership
|
|
56
|
+
|
|
57
|
+
Construction starts no Runtime. Each call resolves the current default pool,
|
|
58
|
+
unless an explicit caller-owned `pool:` was supplied. Runtime reset does not
|
|
59
|
+
transfer ownership of an injected pool.
|
|
60
|
+
|
|
61
|
+
Admission uses `on_full: :raise`: a full or stopped pool raises immediately.
|
|
62
|
+
Queue wait counts toward `timeout`. Cancellation/timeout before worker pickup
|
|
63
|
+
skips the transaction. After work starts, TaskResult may settle while the
|
|
64
|
+
physical transaction continues and commits. A timeout or cancellation is **not
|
|
65
|
+
a rollback guarantee**. The client does not kill a thread, add retries, or claim
|
|
66
|
+
that an uncertain commit succeeded or failed. Applications needing a durable
|
|
67
|
+
outcome must reconcile through their domain's identities and stored state.
|
|
68
|
+
|
|
69
|
+
## Existing Agent, Workflow and coordination operations
|
|
70
|
+
|
|
71
|
+
Internal `Storage::AsyncClient.submit(pool:)` accepts an existing synchronous
|
|
72
|
+
storage unit. This is private framework API, not an application extension API.
|
|
73
|
+
It submits exactly once and adds no transaction, token, or timeout. This lets
|
|
74
|
+
domain operations preserve their own transaction and reconciliation boundaries.
|
|
75
|
+
See the [operation inventory](../architecture/storage-execution-boundaries.md).
|
|
76
|
+
|
|
77
|
+
In particular, a Workflow runner may have only an injected repository rather
|
|
78
|
+
than access to its raw backend. Internal submit therefore accepts a callable
|
|
79
|
+
and the owner's pool; it does not require a dummy backend or a Persistence
|
|
80
|
+
facade. Public transaction_async requires a real SPI 2 backend.
|
|
81
|
+
|
|
82
|
+
Durable commit/readback policy, admission release, callback delivery and the
|
|
83
|
+
application of results to live state remain with Agent/Workflow/MultiAgent.
|
|
84
|
+
No cancellation condition is added to existing terminal saves. Tool execution,
|
|
85
|
+
authorization, tracing and application approval listeners retain their own
|
|
86
|
+
execution boundaries.
|
|
87
|
+
|
|
88
|
+
## ContentStore path and diagram
|
|
89
|
+
|
|
90
|
+
P4 originally moved `ContentStore::StoredContents` into
|
|
91
|
+
`content_store/backends/stored_contents.rb`. [ADR-062](../decisions/062-content-store-service.md)
|
|
92
|
+
supersedes that split: the implementation now lives at
|
|
93
|
+
`content_store/stored_contents.rb`, beside its shared API and owned schema.
|
|
94
|
+
The obsolete backend directory and collapse entry are deleted without a shim.
|
|
95
|
+
Its constant, synchronous operations, digest rules and exceptions are unchanged.
|
|
96
|
+
Use normal `require "phronomy"`; internal file paths are not a public load API.
|
|
97
|
+
Zeitwerk still collapses `storage/async/`. `Storage::Backends` remains a namespace.
|
|
98
|
+
ContentStore receives no artificial async API.
|
|
99
|
+
|
|
100
|
+
M10 is G57 Content Service in B3, outside Backend Contracts/Implementations;
|
|
101
|
+
M73 is retired. M69 Storage AsyncClient stays in B4. Text panels are transparent.
|
|
102
|
+
Arrows targeting M33/M41/M44 are hidden by display settings; all measured
|
|
103
|
+
dependencies, source evidence and matrix cells remain available.
|