phronomy 0.27.0 → 0.29.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.
Files changed (517) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +9 -9
  3. data/CHANGELOG.md +52 -0
  4. data/CONTRIBUTING.md +8 -8
  5. data/README.md +28 -7
  6. data/benchmark/bench_agent_invoke.rb +25 -50
  7. data/benchmark/bench_context_assembler.rb +14 -11
  8. data/benchmark/bench_regression.rb +1 -1
  9. data/benchmark/bench_tool_schema.rb +1 -1
  10. data/docs/application-recipes.md +229 -0
  11. data/docs/architecture/agent-chat-and-state-ownership.md +7 -1
  12. data/docs/architecture/agent-transition-ownership.md +13 -89
  13. data/docs/architecture/backend-groups.md +152 -0
  14. data/docs/architecture/before-llm-input.md +3 -3
  15. data/docs/architecture/context-management.md +1 -1
  16. data/docs/architecture/dx05-agent-scope.md +119 -0
  17. data/docs/architecture/dx05-workflow-task-state.md +134 -0
  18. data/docs/architecture/error-api-review.md +245 -0
  19. data/docs/architecture/execution-abstraction-review.md +88 -0
  20. data/docs/architecture/execution-boundaries.md +28 -0
  21. data/docs/architecture/execution-metadata-and-values.md +6 -0
  22. data/docs/architecture/multi-agent-handoff.md +6 -5
  23. data/docs/architecture/persistence.md +27 -9
  24. data/docs/architecture/r8-unit1.md +104 -0
  25. data/docs/architecture/r8-unit10.md +72 -0
  26. data/docs/architecture/r8-unit11.md +71 -0
  27. data/docs/architecture/r8-unit12.md +67 -0
  28. data/docs/architecture/r8-unit13.md +61 -0
  29. data/docs/architecture/r8-unit14.md +72 -0
  30. data/docs/architecture/r8-unit15.md +65 -0
  31. data/docs/architecture/r8-unit16.md +54 -0
  32. data/docs/architecture/r8-unit17.md +73 -0
  33. data/docs/architecture/r8-unit18.md +92 -0
  34. data/docs/architecture/r8-unit19.md +61 -0
  35. data/docs/architecture/r8-unit2.md +55 -0
  36. data/docs/architecture/r8-unit20.md +51 -0
  37. data/docs/architecture/r8-unit21.md +79 -0
  38. data/docs/architecture/r8-unit22.md +74 -0
  39. data/docs/architecture/r8-unit23.md +81 -0
  40. data/docs/architecture/r8-unit3.md +130 -0
  41. data/docs/architecture/r8-unit4.md +79 -0
  42. data/docs/architecture/r8-unit5.md +115 -0
  43. data/docs/architecture/r8-unit6.md +71 -0
  44. data/docs/architecture/r8-unit7.md +70 -0
  45. data/docs/architecture/r8-unit8.md +78 -0
  46. data/docs/architecture/r8-unit9.md +73 -0
  47. data/docs/architecture/refactoring-closure.md +10 -1
  48. data/docs/architecture/remaining-refactoring-plan.md +16 -0
  49. data/docs/architecture/storage-execution-boundaries.md +54 -0
  50. data/docs/architecture/tool-schema-recording-gap.md +6 -0
  51. data/docs/architecture/tracing.md +1 -1
  52. data/docs/architecture/workflow-terminal-ownership-design.md +2 -2
  53. data/docs/architecture.md +24 -11
  54. data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
  55. data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
  56. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +2 -0
  57. data/docs/decisions/031-durable-multi-agent-coordination.md +2 -0
  58. data/docs/decisions/032-storage-backend-composition.md +5 -0
  59. data/docs/decisions/034-handoff-runner-coordination-ownership.md +2 -0
  60. data/docs/decisions/035-tool-executor-capability-ownership.md +1 -1
  61. data/docs/decisions/038-responsibility-based-source-layout.md +14 -0
  62. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +8 -0
  63. data/docs/decisions/040-configuration-default-composition.md +12 -1
  64. data/docs/decisions/045-worker-input-restriction-ownership.md +4 -0
  65. data/docs/decisions/051-execution-outcome-worker-ownership.md +2 -0
  66. data/docs/decisions/056-workflow-terminal-policy-ownership.md +1 -1
  67. data/docs/decisions/058-neutral-storage-primitives.md +5 -0
  68. data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
  69. data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
  70. data/docs/decisions/061-persistence-failure-contracts.md +89 -0
  71. data/docs/decisions/062-content-store-service.md +52 -0
  72. data/docs/decisions/063-execution-contracts-and-services.md +88 -0
  73. data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
  74. data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
  75. data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
  76. data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
  77. data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
  78. data/docs/decisions/README.md +18 -1
  79. data/docs/execution-boundaries-preview.md +45 -0
  80. data/docs/failure-reason-codes.md +45 -0
  81. data/docs/features.md +12 -4
  82. data/docs/getting-started.md +52 -48
  83. data/docs/migrations/0.22.md +2 -2
  84. data/docs/migrations/durable-semantic-coordination-v2.md +2 -0
  85. data/docs/migrations/handoff-runner-multi-agent.md +2 -0
  86. data/docs/migrations/persistence-failure-contracts.md +67 -0
  87. data/docs/migrations/r8-unit10.md +36 -0
  88. data/docs/migrations/r8-unit11.md +33 -0
  89. data/docs/migrations/r8-unit12.md +31 -0
  90. data/docs/migrations/r8-unit13.md +36 -0
  91. data/docs/migrations/r8-unit14.md +31 -0
  92. data/docs/migrations/r8-unit15.md +31 -0
  93. data/docs/migrations/r8-unit16.md +26 -0
  94. data/docs/migrations/r8-unit17.md +28 -0
  95. data/docs/migrations/r8-unit18.md +29 -0
  96. data/docs/migrations/r8-unit19.md +28 -0
  97. data/docs/migrations/r8-unit20.md +24 -0
  98. data/docs/migrations/r8-unit21.md +28 -0
  99. data/docs/migrations/r8-unit22.md +29 -0
  100. data/docs/migrations/r8-unit23.md +20 -0
  101. data/docs/migrations/r8-unit4.md +67 -0
  102. data/docs/migrations/r8-unit5.md +75 -0
  103. data/docs/migrations/r8-unit6.md +109 -0
  104. data/docs/migrations/r8-unit7.md +31 -0
  105. data/docs/migrations/r8-unit8.md +33 -0
  106. data/docs/migrations/r8-unit9.md +28 -0
  107. data/docs/migrations/storage-async-client.md +103 -0
  108. data/docs/migrations/vector-async-clients.md +110 -0
  109. data/docs/ordered-event-delivery.md +54 -0
  110. data/docs/persistence-backends.md +38 -21
  111. data/docs/runtime-and-concurrency.md +26 -1
  112. data/docs/workflow-completion.md +92 -0
  113. data/gemfiles/http_minimum.gemfile +5 -0
  114. data/lib/phronomy/agent/admission.rb +78 -0
  115. data/lib/phronomy/agent/{lifecycle_contract/agent_already_exists_error.rb → agent_already_exists_error.rb} +1 -1
  116. data/lib/phronomy/agent/{lifecycle_contract/agent_busy_error.rb → agent_busy_error.rb} +1 -1
  117. data/lib/phronomy/agent/agent_not_found_error.rb +16 -0
  118. data/lib/phronomy/agent/{lifecycle_contract/agent_purged_error.rb → agent_purged_error.rb} +1 -1
  119. data/lib/phronomy/agent/agent_unloaded_error.rb +14 -0
  120. data/lib/phronomy/agent/api/agent.rb +13 -0
  121. data/lib/phronomy/{recovery → agent/api}/execution_rehydration_required_error.rb +1 -1
  122. data/lib/phronomy/agent/async_event_api.rb +132 -103
  123. data/lib/phronomy/agent/base.rb +146 -113
  124. data/lib/phronomy/agent/before_llm_input.rb +70 -0
  125. data/lib/phronomy/agent/composition/run_once.rb +1 -1
  126. data/lib/phronomy/agent/{context_assembly/context_candidate_resolver.rb → context_candidate_resolver.rb} +2 -2
  127. data/lib/phronomy/agent/{context_assembly/context_assembler.rb → context_preparation.rb} +35 -221
  128. data/lib/phronomy/agent/control_request.rb +21 -0
  129. data/lib/phronomy/agent/execution/agent_execution.rb +1 -1
  130. data/lib/phronomy/agent/execution/agent_invocation.rb +27 -53
  131. data/lib/phronomy/agent/execution/approval_resume_commit.rb +1 -1
  132. data/lib/phronomy/agent/execution/dispatch_preparation.rb +17 -127
  133. data/lib/phronomy/agent/execution/exact_execution.rb +55 -32
  134. data/lib/phronomy/agent/execution/execution_cancellation.rb +8 -4
  135. data/lib/phronomy/agent/execution/execution_coordinator.rb +229 -407
  136. data/lib/phronomy/agent/execution/execution_metadata.rb +1 -0
  137. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +71 -127
  138. data/lib/phronomy/agent/execution/execution_registry.rb +6 -2
  139. data/lib/phronomy/agent/execution/execution_session_runner.rb +22 -27
  140. data/lib/phronomy/agent/execution/initial_preparation.rb +19 -120
  141. data/lib/phronomy/agent/execution/{agent_invocation_session_builder.rb → invocation_actions.rb} +54 -194
  142. data/lib/phronomy/agent/execution/invocation_transitions.rb +39 -1
  143. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +8 -11
  144. data/lib/phronomy/agent/execution_change.rb +161 -0
  145. data/lib/phronomy/agent/execution_environment.rb +36 -0
  146. data/lib/phronomy/agent/execution_extension_state.rb +21 -0
  147. data/lib/phronomy/agent/execution_observation.rb +35 -0
  148. data/lib/phronomy/agent/filterable.rb +188 -0
  149. data/lib/phronomy/agent/handoff/{handoff_context.rb → transfer_context.rb} +4 -4
  150. data/lib/phronomy/agent/handoff/{handoff_projection.rb → transfer_projection.rb} +14 -33
  151. data/lib/phronomy/{llm_contract/transport_error.rb → agent/handoff_error.rb} +1 -1
  152. data/lib/phronomy/agent/journal/journal_projection.rb +1 -1
  153. data/lib/phronomy/agent/knowledge_item.rb +13 -0
  154. data/lib/phronomy/agent/lifecycle/agent_root.rb +1 -1
  155. data/lib/phronomy/agent/lifecycle/lifetime_api.rb +76 -0
  156. data/lib/phronomy/agent/lifecycle/operation_lease.rb +33 -0
  157. data/lib/phronomy/agent/lifecycle/operation_result.rb +53 -0
  158. data/lib/phronomy/agent/lifecycle/ownership_registry.rb +117 -31
  159. data/lib/phronomy/agent/lifecycle/scope.rb +198 -0
  160. data/lib/phronomy/agent/lifecycle/scope_cleanup_error.rb +19 -0
  161. data/lib/phronomy/agent/lifecycle/unload_transition.rb +78 -0
  162. data/lib/phronomy/agent/persistence/agent_repository.rb +29 -21
  163. data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
  164. data/lib/phronomy/agent/persistence/codec.rb +1 -21
  165. data/lib/phronomy/agent/persistence/execution_repository.rb +57 -41
  166. data/lib/phronomy/agent/persistence/journal_repository.rb +27 -18
  167. data/lib/phronomy/agent/persistence/records.rb +33 -0
  168. data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
  169. data/lib/phronomy/agent/persistence/storage_schema.rb +7 -2
  170. data/lib/phronomy/agent/persistence/watermark.rb +13 -11
  171. data/lib/phronomy/agent/recovery/invocation_restorer.rb +13 -21
  172. data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +13 -12
  173. data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +34 -34
  174. data/lib/phronomy/agent/recovery/recovery_coordinator/resolution.rb +33 -39
  175. data/lib/phronomy/agent/recovery/recovery_coordinator.rb +28 -25
  176. data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
  177. data/lib/phronomy/agent/recovery/recovery_support.rb +10 -19
  178. data/lib/phronomy/agent/reserved_execution.rb +16 -0
  179. data/lib/phronomy/agent/retention.rb +17 -0
  180. data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
  181. data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
  182. data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
  183. data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
  184. data/lib/phronomy/agent/{context_assembly/ruby_llm_materializer.rb → runtime_input.rb} +18 -35
  185. data/lib/phronomy/agent/{context_assembly/saved_context_reader.rb → saved_context_reader.rb} +6 -4
  186. data/lib/phronomy/agent/settings.rb +47 -0
  187. data/lib/phronomy/agent/{context_assembly/state_writer.rb → state_writer.rb} +4 -3
  188. data/lib/phronomy/agent/store.rb +253 -0
  189. data/lib/phronomy/agent/{lifecycle_contract/stream_callback_error.rb → stream_callback_error.rb} +3 -3
  190. data/lib/phronomy/agent/tool_execution/tool_binding.rb +4 -64
  191. data/lib/phronomy/agent/tool_execution/tool_invocation.rb +50 -219
  192. data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
  193. data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
  194. data/lib/phronomy/common/error.rb +65 -1
  195. data/lib/phronomy/configuration/runtime_settings.rb +49 -0
  196. data/lib/phronomy/content_store/base.rb +7 -2
  197. data/lib/phronomy/content_store/storage_schema.rb +1 -0
  198. data/lib/phronomy/content_store/stored_contents.rb +2 -1
  199. data/lib/phronomy/context/assembly.rb +195 -0
  200. data/lib/phronomy/{llm_contract/context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +3 -1
  201. data/lib/phronomy/context/candidate.rb +51 -0
  202. data/lib/phronomy/context/constraint.rb +47 -0
  203. data/lib/phronomy/{agent/context_contract → context}/context_plan.rb +1 -1
  204. data/lib/phronomy/{agent/context_contract → context}/context_plan_validator.rb +3 -3
  205. data/lib/phronomy/{agent/context_contract → context}/context_policy.rb +1 -1
  206. data/lib/phronomy/{agent/context_contract → context}/context_policy_input.rb +1 -1
  207. data/lib/phronomy/{agent/context_assembly → context}/context_policy_input_builder.rb +1 -1
  208. data/lib/phronomy/context/default_policy.rb +140 -0
  209. data/lib/phronomy/context/final_budget_validator.rb +33 -0
  210. data/lib/phronomy/{agent/context_contract → context}/llm_input_build_context.rb +1 -1
  211. data/lib/phronomy/{agent/context_contract → context}/llm_input_manifest.rb +19 -19
  212. data/lib/phronomy/{agent/context_contract → context}/llm_input_patch.rb +1 -1
  213. data/lib/phronomy/context/manifest_error.rb +10 -0
  214. data/lib/phronomy/context/prompt_template.rb +98 -0
  215. data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
  216. data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
  217. data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
  218. data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
  219. data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
  220. data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
  221. data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
  222. data/lib/phronomy/embeddings/async/async_client.rb +44 -0
  223. data/lib/phronomy/embeddings/authentication_error.rb +11 -0
  224. data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +52 -0
  225. data/lib/phronomy/embeddings/base.rb +43 -0
  226. data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
  227. data/lib/phronomy/embeddings/rate_limit_error.rb +11 -0
  228. data/lib/phronomy/embeddings/transport_error.rb +11 -0
  229. data/lib/phronomy/engine/concurrency/offload_pool.rb +36 -21
  230. data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
  231. data/lib/phronomy/engine/diagnostics.rb +1 -1
  232. data/lib/phronomy/engine/event_loop.rb +7 -7
  233. data/lib/phronomy/engine/execution_binding.rb +23 -0
  234. data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
  235. data/lib/phronomy/engine/fsm_protocol.rb +1 -6
  236. data/lib/phronomy/engine/fsm_session.rb +3 -3
  237. data/lib/phronomy/engine/metrics.rb +16 -14
  238. data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
  239. data/lib/phronomy/engine/runtime.rb +25 -12
  240. data/lib/phronomy/engine/terminal_decision.rb +7 -0
  241. data/lib/phronomy/execution/async_operation.rb +41 -0
  242. data/lib/phronomy/{engine → execution}/blocking.rb +2 -2
  243. data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +1 -1
  244. data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
  245. data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
  246. data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
  247. data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
  248. data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
  249. data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
  250. data/lib/phronomy/{engine → execution}/execution.rb +61 -27
  251. data/lib/phronomy/{engine → execution}/execution_cancellation_error.rb +2 -2
  252. data/lib/phronomy/execution/execution_receiver.rb +78 -0
  253. data/lib/phronomy/execution/execution_scope_state.rb +35 -0
  254. data/lib/phronomy/{engine → execution}/execution_timeout_error.rb +2 -2
  255. data/lib/phronomy/{engine → execution}/invocation_context.rb +0 -15
  256. data/lib/phronomy/execution/invocation_controls.rb +73 -0
  257. data/lib/phronomy/execution/runnable.rb +24 -0
  258. data/lib/phronomy/{engine → execution}/task_result.rb +9 -4
  259. data/lib/phronomy/execution/wait_policy.rb +24 -0
  260. data/lib/phronomy/filter/{contract/filter_block_error.rb → filter_block_error.rb} +3 -3
  261. data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
  262. data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
  263. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +2 -2
  264. data/lib/phronomy/generation/generator_verifier.rb +7 -7
  265. data/lib/phronomy/generation/low_confidence_error.rb +2 -2
  266. data/lib/phronomy/integrations/ordered_event_delivery.rb +208 -0
  267. data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
  268. data/lib/phronomy/{llm_contract → llm_adapter}/authentication_error.rb +3 -1
  269. data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
  270. data/lib/phronomy/llm_adapter/base.rb +49 -68
  271. data/lib/phronomy/{llm_contract → llm_adapter}/context_length_error.rb +3 -1
  272. data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
  273. data/lib/phronomy/llm_adapter/message.rb +62 -0
  274. data/lib/phronomy/{llm_contract → llm_adapter}/rate_limit_error.rb +3 -1
  275. data/lib/phronomy/llm_adapter/request.rb +79 -0
  276. data/lib/phronomy/llm_adapter/response.rb +36 -0
  277. data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
  278. data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
  279. data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
  280. data/lib/phronomy/llm_adapter.rb +3 -16
  281. data/lib/phronomy/multi_agent/admission_registry.rb +1 -8
  282. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
  283. data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
  284. data/lib/phronomy/{agent/handoff → multi_agent}/handoff.rb +2 -2
  285. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_capability_factory.rb +21 -2
  286. data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
  287. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_policy.rb +1 -1
  288. data/lib/phronomy/multi_agent/handoff_runner.rb +77 -100
  289. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_state.rb +1 -1
  290. data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
  291. data/lib/phronomy/multi_agent/persistence/codec.rb +20 -0
  292. data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
  293. data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
  294. data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
  295. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +60 -44
  296. data/lib/phronomy/multi_agent/persistence/team_repository.rb +29 -21
  297. data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
  298. data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
  299. data/lib/phronomy/multi_agent/shared_state.rb +2 -2
  300. data/lib/phronomy/multi_agent/store.rb +156 -0
  301. data/lib/phronomy/multi_agent/team_busy_error.rb +18 -0
  302. data/lib/phronomy/multi_agent/team_coordinator.rb +99 -77
  303. data/lib/phronomy/multi_agent/team_not_found_error.rb +18 -0
  304. data/lib/phronomy/multi_agent/team_ownership_registry.rb +2 -12
  305. data/lib/phronomy/output_parser/parse_error.rb +7 -0
  306. data/lib/phronomy/persistence/content_repository.rb +26 -0
  307. data/lib/phronomy/persistence/errors.rb +16 -0
  308. data/lib/phronomy/persistence/migration/initial_format_migration.rb +2 -2
  309. data/lib/phronomy/persistence/persistence.rb +23 -0
  310. data/lib/phronomy/persistence/save_outcome.rb +24 -0
  311. data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
  312. data/lib/phronomy/persistence/storage_boundary.rb +32 -0
  313. data/lib/phronomy/persistence/transaction.rb +86 -0
  314. data/lib/phronomy/persistence_composition/storage_schema.rb +9 -4
  315. data/lib/phronomy/persistence_composition/stores.rb +34 -0
  316. data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
  317. data/lib/phronomy/runtime_composition/agent_defaults.rb +5 -1
  318. data/lib/phronomy/runtime_composition/configuration.rb +146 -0
  319. data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
  320. data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
  321. data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
  322. data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
  323. data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
  324. data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
  325. data/lib/phronomy/storage/async/async_client.rb +60 -0
  326. data/lib/phronomy/storage/backend.rb +8 -2
  327. data/lib/phronomy/storage/condition_failed_error.rb +2 -2
  328. data/lib/phronomy/storage/unique_constraint_error.rb +2 -2
  329. data/lib/phronomy/testing/eval/metrics.rb +1 -1
  330. data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
  331. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +2 -2
  332. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +6 -6
  333. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +55 -52
  334. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +3 -3
  335. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +7 -7
  336. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +11 -11
  337. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +57 -51
  338. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +1 -1
  339. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +23 -22
  340. data/lib/phronomy/tool/authorization.rb +77 -0
  341. data/lib/phronomy/tool/base.rb +551 -9
  342. data/lib/phronomy/tool/call_request.rb +40 -0
  343. data/lib/phronomy/{agent/tool_execution/tool_definition_set.rb → tool/definition_set.rb} +7 -8
  344. data/lib/phronomy/tool/operation.rb +88 -0
  345. data/lib/phronomy/tool/schema.rb +214 -0
  346. data/lib/phronomy/tool/settings.rb +31 -0
  347. data/lib/phronomy/tool/tool_error.rb +7 -0
  348. data/lib/phronomy/tool/tool_executor.rb +58 -0
  349. data/lib/phronomy/tools/agent.rb +22 -90
  350. data/lib/phronomy/tools/mcp.rb +21 -14
  351. data/lib/phronomy/tools/vector_search.rb +4 -4
  352. data/lib/phronomy/tracing/automatic.rb +11 -6
  353. data/lib/phronomy/tracing/base.rb +36 -7
  354. data/lib/phronomy/tracing/observation.rb +37 -0
  355. data/lib/phronomy/tracing/open_telemetry_tracer.rb +4 -29
  356. data/lib/phronomy/tracing/settings.rb +36 -0
  357. data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
  358. data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
  359. data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
  360. data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
  361. data/lib/phronomy/vector_store/base.rb +118 -49
  362. data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
  363. data/lib/phronomy/vector_store.rb +2 -17
  364. data/lib/phronomy/version.rb +1 -1
  365. data/lib/phronomy/workflow/completion.rb +11 -0
  366. data/lib/phronomy/workflow/execution/workflow.rb +37 -9
  367. data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
  368. data/lib/phronomy/workflow/execution/workflow_context.rb +2 -2
  369. data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +28 -0
  370. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +77 -8
  371. data/lib/phronomy/workflow/execution/workflow_runner.rb +105 -92
  372. data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
  373. data/lib/phronomy/workflow/execution/workflow_task_execution.rb +153 -0
  374. data/lib/phronomy/workflow/execution/workflow_task_reception.rb +72 -0
  375. data/lib/phronomy/workflow/execution/workflow_task_resume_error.rb +14 -0
  376. data/lib/phronomy/workflow/persistence/state_repository.rb +28 -22
  377. data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
  378. data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +61 -0
  379. data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +158 -0
  380. data/lib/phronomy/workflow/runtime_binding/workflow_task_session.rb +76 -0
  381. data/lib/phronomy/workflow/{execution → runtime_binding}/workflow_terminal_policy.rb +4 -4
  382. data/lib/phronomy.rb +63 -16
  383. data/scripts/api_snapshot.rb +47 -15
  384. data/scripts/check_readme_ruby.rb +24 -29
  385. data/scripts/check_readme_runnable.rb +92 -81
  386. data/sig/_private/phronomy/agent/settings.rbs +19 -0
  387. data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
  388. data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
  389. data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
  390. data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
  391. data/sig/_private/phronomy/tool/settings.rbs +13 -0
  392. data/sig/_private/phronomy/tracing/settings.rbs +15 -0
  393. data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
  394. data/sig/phronomy/agent/admission.rbs +19 -0
  395. data/sig/phronomy/agent/agent_not_found_error.rbs +6 -0
  396. data/sig/phronomy/agent/agent_unloaded_error.rbs +6 -0
  397. data/sig/phronomy/agent/execution_contract.rbs +132 -0
  398. data/sig/phronomy/agent/execution_environment.rbs +20 -0
  399. data/sig/phronomy/agent/store.rbs +73 -0
  400. data/sig/phronomy/agent/stream_callback_error.rbs +8 -0
  401. data/sig/phronomy/agent.rbs +29 -135
  402. data/sig/phronomy/common.rbs +7 -0
  403. data/sig/phronomy/content_store/contracts.rbs +13 -0
  404. data/sig/phronomy/context.rbs +152 -0
  405. data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
  406. data/sig/phronomy/embeddings/base.rbs +23 -0
  407. data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
  408. data/sig/phronomy/engine/control_bindings.rbs +11 -0
  409. data/sig/phronomy/engine/control_protocols.rbs +23 -0
  410. data/sig/phronomy/engine/execution_binding.rbs +6 -0
  411. data/sig/phronomy/engine/execution_receiver.rbs +15 -0
  412. data/sig/phronomy/engine/observability.rbs +13 -0
  413. data/sig/phronomy/execution/async_operation.rbs +7 -0
  414. data/sig/phronomy/execution/blocking.rbs +5 -0
  415. data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
  416. data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
  417. data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
  418. data/sig/phronomy/execution/control_protocols.rbs +18 -0
  419. data/sig/phronomy/execution/errors.rbs +7 -0
  420. data/sig/phronomy/execution/execution.rbs +41 -0
  421. data/sig/phronomy/execution/execution_receiver.rbs +40 -0
  422. data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
  423. data/sig/phronomy/execution/invocation_context.rbs +18 -0
  424. data/sig/phronomy/execution/invocation_controls.rbs +13 -0
  425. data/sig/phronomy/execution/task_result.rbs +29 -0
  426. data/sig/phronomy/extensions.rbs +1 -21
  427. data/sig/phronomy/filter/filter_block_error.rbs +6 -0
  428. data/sig/phronomy/generation/low_confidence_error.rbs +6 -0
  429. data/sig/phronomy/handoff.rbs +10 -4
  430. data/sig/phronomy/integrations.rbs +14 -0
  431. data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
  432. data/sig/phronomy/llm_adapter/base.rbs +14 -0
  433. data/sig/phronomy/llm_adapter/usage.rbs +14 -0
  434. data/sig/phronomy/llm_adapter/values.rbs +43 -0
  435. data/sig/phronomy/llm_context_window.rbs +10 -0
  436. data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
  437. data/sig/phronomy/multi_agent/store.rbs +54 -0
  438. data/sig/phronomy/multi_agent/team_busy_error.rbs +8 -0
  439. data/sig/phronomy/multi_agent/team_not_found_error.rbs +8 -0
  440. data/sig/phronomy/multi_agent.rbs +6 -3
  441. data/sig/phronomy/persistence/errors.rbs +18 -0
  442. data/sig/phronomy/persistence/migration.rbs +13 -0
  443. data/sig/phronomy/persistence/transaction.rbs +19 -0
  444. data/sig/phronomy/persistence.rbs +1 -99
  445. data/sig/phronomy/persistence_composition.rbs +19 -0
  446. data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
  447. data/sig/phronomy/storage/async/async_client.rbs +8 -0
  448. data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
  449. data/sig/phronomy/{storage.rbs → storage/contracts.rbs} +4 -18
  450. data/sig/phronomy/tool.rbs +48 -4
  451. data/sig/phronomy/tracing/observation.rbs +7 -0
  452. data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
  453. data/sig/phronomy/vector_store/base.rbs +23 -0
  454. data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +15 -0
  455. data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
  456. data/sig/phronomy/workflow/store.rbs +8 -0
  457. data/sig/phronomy/workflow.rbs +5 -1
  458. data/sig/phronomy.rbs +4 -49
  459. metadata +365 -117
  460. data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
  461. data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
  462. data/lib/phronomy/agent/concerns/filterable.rb +0 -184
  463. data/lib/phronomy/agent/context/capability/base.rb +0 -548
  464. data/lib/phronomy/agent/context/capability/tool_executor.rb +0 -62
  465. data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
  466. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +0 -36
  467. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +0 -22
  468. data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
  469. data/lib/phronomy/agent/context_policies/default.rb +0 -142
  470. data/lib/phronomy/agent/execution/phase_machine_builder.rb +0 -101
  471. data/lib/phronomy/agent/execution/provider_call_outcome.rb +0 -106
  472. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +0 -15
  473. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +0 -131
  474. data/lib/phronomy/agent/handoff/handoff_request.rb +0 -45
  475. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +0 -7
  476. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +0 -58
  477. data/lib/phronomy/agent/persistence/queries.rb +0 -61
  478. data/lib/phronomy/agent/selection/candidate.rb +0 -53
  479. data/lib/phronomy/agent/selection/constraint.rb +0 -49
  480. data/lib/phronomy/agent/tool_execution/tool_call_intercepted.rb +0 -29
  481. data/lib/phronomy/agent/tool_execution/tool_invocation_session_builder.rb +0 -276
  482. data/lib/phronomy/configuration/configuration.rb +0 -68
  483. data/lib/phronomy/configuration/global_configuration.rb +0 -26
  484. data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
  485. data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
  486. data/lib/phronomy/engine/execution_receiver.rb +0 -65
  487. data/lib/phronomy/engine/runnable.rb +0 -54
  488. data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
  489. data/lib/phronomy/llm_contract/token_usage.rb +0 -85
  490. data/lib/phronomy/multi_agent/persistence/queries.rb +0 -30
  491. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +0 -15
  492. data/lib/phronomy/output_parser/contract/parse_error.rb +0 -7
  493. data/lib/phronomy/persistence/api/persistence.rb +0 -140
  494. data/lib/phronomy/persistence_composition/repositories.rb +0 -77
  495. data/lib/phronomy/recovery/recovery.rb +0 -186
  496. data/lib/phronomy/tool/contract/tool_error.rb +0 -7
  497. data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
  498. data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
  499. data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
  500. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +0 -9
  501. data/sig/phronomy/execution_receiver.rbs +0 -34
  502. data/sig/phronomy/llm_adapter.rbs +0 -11
  503. data/sig/phronomy/runtime.rbs +0 -76
  504. /data/lib/phronomy/agent/{context_assembly/context_importer.rb → context_importer.rb} +0 -0
  505. /data/lib/phronomy/{engine → execution}/backpressure_error.rb +0 -0
  506. /data/lib/phronomy/{engine → execution}/cancellation_error.rb +0 -0
  507. /data/lib/phronomy/{engine → execution}/concurrency/worker_input_restricted.rb +0 -0
  508. /data/lib/phronomy/{engine → execution}/event_loop_reentrancy_error.rb +0 -0
  509. /data/lib/phronomy/{engine → execution}/invalid_async_entry_action_error.rb +0 -0
  510. /data/lib/phronomy/{engine → execution}/invalid_async_transition_action_error.rb +0 -0
  511. /data/lib/phronomy/{engine → execution}/invalid_async_workflow_action_error.rb +0 -0
  512. /data/lib/phronomy/{engine → execution}/pool_shutdown_error.rb +0 -0
  513. /data/lib/phronomy/{engine → execution}/recursion_limit_error.rb +0 -0
  514. /data/lib/phronomy/{engine → execution}/runtime_shutdown_error.rb +0 -0
  515. /data/lib/phronomy/{engine → execution}/runtime_shutdown_reentrancy_error.rb +0 -0
  516. /data/lib/phronomy/{engine → execution}/scheduler_reentrancy_error.rb +0 -0
  517. /data/lib/phronomy/{engine → execution}/timeout_error.rb +0 -0
@@ -0,0 +1,38 @@
1
+ # ADR-065: Vector and Embeddings common operations
2
+
3
+ Status: accepted for the authorized r8 unit 5 implementation. Actual-service
4
+ verification is reported separately from the design decision.
5
+
6
+ This amends ADR-059's vector/embedding extension and namespace provisions.
7
+ Its synchronous backend boundary, separate AsyncClients and no production worker
8
+ Threads rule remain in force. It implements C10/C11 and DP09/DP10 from the agreed
9
+ contract foundation target.
10
+
11
+ VectorStore::Base and Embeddings::Base own the public operation templates,
12
+ validation and cancellation checkpoint. Concrete backends override protected
13
+ perform_* hooks, retaining algorithms, database/SDK adaptation and physical state.
14
+ VectorStore does not require an embedding provider, and Embeddings does not depend
15
+ on VectorStore. Documents groups the existing Loader/Splitter helpers without
16
+ creating another domain Contract.
17
+
18
+ Placement is decided by domain meaning and observable rules, not shared use.
19
+ Generic reusable code does not become a Contract merely because multiple callers
20
+ need it. Database response parsing and SDK/serialization adaptation remain
21
+ implementation responsibilities even when several backends perform similar work.
22
+
23
+ Malformed public inputs fail before backend I/O. Malformed backend results fail
24
+ explicitly. Provider exceptions are adapted at the provider boundary, never by
25
+ rescuing arbitrary application failures in the common framework. No generic retry,
26
+ commit reconciliation or stronger concurrency guarantee is added.
27
+
28
+ Backends must reject malformed external data before converting it to the public
29
+ result. Redis RESP2 fields/counts/distances and Pgvector rows/JSON are decoded
30
+ inside their own backends, with `VectorStore::InvalidResultError` as the public
31
+ failure for invalid data. Legitimate absent metadata and Redis's documented
32
+ expired-document response are distinguished from corruption. The common Base
33
+ then validates the domain result; it contains no external-protocol decoder.
34
+
35
+ Old namespaces and public-template overrides are intentionally replaced without
36
+ compatibility aliases. Runtime API, RBS, contract tests, examples and migration
37
+ guidance move together. See [unit 5](../architecture/r8-unit5.md) and
38
+ [migration](../migrations/r8-unit5.md).
@@ -0,0 +1,20 @@
1
+ # ADR-066: LLM and Tool operation contracts
2
+
3
+ Status: Accepted for the r8 unit 6 candidate; application verification is separate.
4
+
5
+ C09 owns model-turn values, operation invariants, usage and failures. C06 owns Tool
6
+ requests, schemas, validation, authorization and execution rules. Shared usage is
7
+ not a placement criterion. SDK wire parsing/rendering and callback interception
8
+ remain in the RubyLLM backend. Agent owns context, approval, durable execution and
9
+ recovery; AsyncClient submits the complete backend operation to Execution.
10
+
11
+ Tool::Base becomes independent of RubyLLM::Tool. The schema used for advertisement
12
+ is also the validation source for both declaration paths. C09 depends only on C06
13
+ value/schema semantics, never executable Tool instances. Protected hooks allow a
14
+ minimal independent backend; public complete/stream enforce the common contract.
15
+ No forwarding namespace or legacy SDK-shaped adapter SPI is retained.
16
+
17
+ Consequences and compatibility are recorded in
18
+ [unit 6 architecture](../architecture/r8-unit6.md) and
19
+ [unit 6 migration](../migrations/r8-unit6.md). Existing pending execution schema
20
+ comparisons remain strict; deployment must account for changed Tool definitions.
@@ -0,0 +1,29 @@
1
+ # ADR-067: Agent progress owns policy; composition supplies its execution connection
2
+
3
+ Status: accepted for r8 unit 7 candidate. Supersedes the construction ownership
4
+ portion of the Agent transition design; durable guarantees are unchanged.
5
+
6
+ ## Decision
7
+
8
+ Keep progress rules, entry operations, admission, approval and recovery decisions
9
+ inside Agent. Introduce the private ExecutionEnvironment connection and an Engine
10
+ implementation. Bind a live Agent to the environment of its ownership registry.
11
+ Move concrete session/phase-machine construction to agent/runtime_binding.
12
+ Keep state_machines out of InvocationTransitions. Extract the serial receiver
13
+ lifecycle framework to Execution with an Engine-owned channel implementation.
14
+
15
+ ## Why
16
+
17
+ The old session builder mixed domain operations with concrete FSM construction.
18
+ Repeated Runtime.instance lookups made execution connection selection implicit.
19
+ Moving all code into a binding would relocate the same semantic mixture.
20
+ A contract owns executable rules, not just signatures or forwarding methods.
21
+
22
+ ## Consequences
23
+
24
+ The application invoke/stream/approval/recovery API is unchanged. Internal
25
+ AgentInvocationSessionBuilder is removed with no alias. Private receiver
26
+ constructors now accept a channel. Internal embedders must adopt the composition
27
+ port and respect serial mutation, bounded submission, shutdown and session
28
+ incarnation rules. Tool child and other domain FSM decomposition remain separate
29
+ work. See ../architecture/r8-unit7.md for scope and verification.
@@ -0,0 +1,36 @@
1
+ # ADR-068: Agent owns Tool child progress; Tool owns its operation protocol
2
+
3
+ Status: accepted for the r8 unit 8 candidate. Extends
4
+ [067-agent-progress-and-engine-connection](067-agent-progress-and-engine-connection.md)
5
+ to Tool children and refines the operation boundary in
6
+ [066-llm-and-tool-operation-contracts](066-llm-and-tool-operation-contracts.md).
7
+
8
+ ## Decision
9
+
10
+ Keep Tool child transitions, approval waiting, dispatch eligibility, outcome
11
+ application and parent notification in C04. Use one ordered transition definition
12
+ for both concrete FSM construction and source admission. Move FSMSession and
13
+ state_machines construction into Agent runtime_binding. Pass the original Agent
14
+ execution environment explicitly to child authorization and execution.
15
+
16
+ C06 owns standard/custom Tool operation dispatch, execution-mode validity,
17
+ completion protocol and result adaptation. It accepts the C13 submitter protocol
18
+ for standard offloaded work. Agent uses the public operation rather than
19
+ inspecting the implementation owner and calling the private default executor.
20
+ Custom Tool#call_async overrides keep their public signature and own mechanism.
21
+
22
+ ## Reason
23
+
24
+ The previous builder mixed Agent rules with concrete connections and duplicated
25
+ transition definitions. Agent also selected Tool implementation paths in both
26
+ invocation and result binding. Moving whole classes to an adapter or assigning
27
+ all Tool-related progress to C06 would preserve or misplace those responsibilities.
28
+
29
+ ## Consequences
30
+
31
+ The boundary now supports independent Agent policy tests and Engine adaptation
32
+ tests. No concrete Runtime or Agent type enters C06. Existing durable identity,
33
+ approval/recovery, causal revision and physical-quiescence guarantees remain.
34
+ No new exactly-once or in-flight version compatibility is claimed. See
35
+ [the unit 8 scope](../architecture/r8-unit8.md) and
36
+ [migration instructions](../migrations/r8-unit8.md).
@@ -88,7 +88,7 @@ resolved explicitly.
88
88
  | [`037-common-definition-ownership`](037-common-definition-ownership.md) | Amended | Yes | Defines the common responsibility group and initially extracts the shared base exception; [038-responsibility-based-source-layout](038-responsibility-based-source-layout.md) extends the extraction scope while preserving ownership rules and exception contracts. |
89
89
  | [`038-responsibility-based-source-layout`](038-responsibility-based-source-layout.md) | Amended | Yes | Reserves the direct root for version/namespace loading, groups common definitions and feature implementation/contracts, and preserves canonical constants and lifecycle loading through explicit Zeitwerk roots. ADR-039 separates cross-owner Runtime lifecycle coordination. |
90
90
  | [`039-runtime-configuration-lifecycle-ownership`](039-runtime-configuration-lifecycle-ownership.md) | Amended | Yes | Separates application Runtime reset and configuration replacement into runtime_composition; configuration access and Engine mechanics retain their own ownership and existing API behavior. ADR-040 separates concrete-default selection without changing Runtime reset. |
91
- | [`040-configuration-default-composition`](040-configuration-default-composition.md) | Accepted | Yes | Settings consume internal fresh-instance factories; runtime_composition selects and binds the concrete adapter/tracer defaults. Preserves Configuration.new and the adapter SPI. |
91
+ | [`040-configuration-default-composition`](040-configuration-default-composition.md) | Amended | Yes | Settings consume internal fresh-instance factories; runtime_composition selects and binds the concrete adapter/tracer defaults. Preserves Configuration.new and the adapter SPI. |
92
92
  | [`041-feature-owned-identity-registries`](041-feature-owned-identity-registries.md) | Accepted | Yes | Agent and MultiAgent own identity registries; Runtime retains them through generic lookup, drain/wait, and optional finalization. Preserves product APIs and single-owner lifetime; Execution state is separately assigned by ADR-042. |
93
93
 
94
94
  | [`042-feature-owned-execution-state`](042-feature-owned-execution-state.md) | Accepted | Yes | Agent/Workflow own execution state; Engine retains generic receiver delivery, synchronization and shutdown boundaries. Single-writer and durable barriers remain. |
@@ -110,6 +110,15 @@ resolved explicitly.
110
110
 
111
111
  | [`058-neutral-storage-primitives`](058-neutral-storage-primitives.md) | Accepted | Yes | Neutral Records/Streams/Blobs SPI 2 and scoped transaction lifecycle; amends 032, 033, 043 and 057. |
112
112
 
113
+ | [`059-backend-contracts-and-async-clients`](059-backend-contracts-and-async-clients.md) | Accepted | Yes | P1/P2 separates synchronous LLM contracts, implementations and internal clients; independent responsibility groups replace numbered layers. VectorStore/Storage migration remains pending. |
114
+ | [`060-runtime-settings-and-application-configuration`](060-runtime-settings-and-application-configuration.md) | Accepted | Yes | Separates neutral Engine settings from typed application Configuration; preserves public settings/lifecycle semantics and requires the complete Ruby + RBS boundary gate without exceptions. |
115
+
116
+ | [`061-persistence-failure-contracts`](061-persistence-failure-contracts.md) | Accepted | Yes | Independent domain failure contracts and explicit raw Storage translation; public rescue-clause migration, preserved transaction/admission/uncertainty semantics. |
117
+ | [`062-content-store-service`](062-content-store-service.md) | Accepted | Yes | Content management over neutral Storage; removes the unnecessary backend subdivision and preserves content/Persistence behavior. |
118
+
119
+ | [`063-execution-contracts-and-services`](063-execution-contracts-and-services.md) | Accepted | Yes | Shared execution contracts and result/call services separated from Engine internals; preserves public APIs and fixes filtered physical completion. |
120
+ | [`068-agent-tool-child-progress-and-tool-operation`](068-agent-tool-child-progress-and-tool-operation.md) | Accepted | Yes | C04 Tool child progress and original environment; C06 operation dispatch/result adaptation; child FSM in runtime_binding. |
121
+
113
122
  ## Legacy duplicate `011`
114
123
 
115
124
  The repository intentionally preserves both legacy files:
@@ -203,3 +212,11 @@ Current explanatory architecture starts at
203
212
  segregated under `docs/archive/design/` and are non-normative. Explanatory
204
213
  architecture documents describe the reconciled current system but do not
205
214
  supersede ADRs merely by being newer.
215
+
216
+ - [`064-agent-execution-and-multi-agent-responsibility`](064-agent-execution-and-multi-agent-responsibility.md)
217
+
218
+ - [`065-vector-and-embeddings-common-operations`](065-vector-and-embeddings-common-operations.md) — accepted for r8 unit 5; amends the vector/embedding SPI and namespace provisions of ADR-059.
219
+
220
+ - [`066-llm-and-tool-operation-contracts`](066-llm-and-tool-operation-contracts.md)
221
+
222
+ - [`067-agent-progress-and-engine-connection`](067-agent-progress-and-engine-connection.md) — Agent progress rules and Engine connection ownership.
@@ -0,0 +1,45 @@
1
+ # Execution boundary candidate (unapplied)
2
+
3
+ Base: main 653e255a34fe4062d4beca47530e084fdd3a6ba9.
4
+ This is an unpublished prototype for source-derived architecture review.
5
+
6
+ TaskResult, Outcome, result composition, physical completion and ScopeState
7
+ belong to Execution Results. They depend on Contracts and Common, without
8
+ acquiring Runtime or calling Execution Services. Engine and Services share
9
+ these neutral results. OffloadPool uses an injected timer protocol; its wait
10
+ guard uses WaitPolicy. Services owns operation binding, timer subscriptions,
11
+ worker submission and invocation-control adaptation.
12
+
13
+ Workflow::Completion owns the public DSL finish value `:__finish__`.
14
+ WorkflowPhaseMachineBuilder, beside WorkflowRunner, translates it to the FSM
15
+ terminal state. FSMSession retains terminal detection and persistence gating.
16
+ TerminalDecision is an execution contract, independent of Workflow and FSM
17
+ state vocabulary.
18
+
19
+ ## Intentional compatibility changes
20
+
21
+ * InvocationContext#effective_timeout_token and #effective_cancellation_token
22
+ are removed. Although annotated private, both occurred in the Stable API
23
+ snapshot. This candidate updates those two entries explicitly. Applications
24
+ pass cancellation_token/deadline into InvocationContext; the invoking
25
+ service applies them. Code needing a standalone token constructs
26
+ Concurrency::CancellationToken directly.
27
+ * Deadline#attach_to is removed. Deadline is a time value, not a timer owner.
28
+ Internal Workflow control adaptation moves to InvocationControls.
29
+ * Unused private CancellationScope is removed. Private
30
+ Workflow::PhaseMachineBuilder becomes WorkflowPhaseMachineBuilder in the
31
+ Runner source directory. FSMProtocol::TerminalDecision becomes
32
+ Phronomy::TerminalDecision. Direct requires of moved internal files change.
33
+ * An already expired Workflow deadline now cancels immediately. An explicitly
34
+ supplied token still takes precedence over that deadline, as before.
35
+
36
+ TaskResult/map/flat_map/all_settled and AsyncClient public operations remain.
37
+ WorkerSubmission preserves injected-pool ownership, original result identity,
38
+ operation-time Runtime resolution and synchronous admission errors. Blocking
39
+ continues converting admission errors to failed results. MCP keeps its named
40
+ cleanup pool. Engine connections remain with registries/coordinators/runners.
41
+
42
+ RBS declares scope, timer, receiver and terminal-policy protocols in sig/.
43
+ Validation checks signature consistency, not whole-program type correctness.
44
+ The static diagram includes Ruby and RBS evidence; injected implementations
45
+ and callback behavior also require runtime tests.
@@ -0,0 +1,45 @@
1
+ # Failure reason codes
2
+
3
+ `Phronomy::Error` and its subclasses accept an optional `code:` String and expose
4
+ it through `error.code`. Unspecified codes are nil. Supplied strings are copied
5
+ and frozen. Existing message, class, cause and backtrace behavior is retained.
6
+ No change is made to StandardError or third-party exceptions.
7
+
8
+ This is an additive public-contract extension. `class` and `message` remain in
9
+ saved failure diagnostics. When a Phronomy exception has a code, its diagnostic
10
+ also contains `"code"`. The same generic field is retained through Agent failure
11
+ persistence, Team results, and terminal resume/reboot. A code is not an execution
12
+ status and is not a retry permission.
13
+
14
+ | Code | Owner and meaning |
15
+ |---|---|
16
+ | `team.enqueue_after_finalize` | MultiAgent: a new enqueue was conclusively rejected after finalization, following the existing readback checks |
17
+
18
+ The operation wrapper remains catchable as ConfigurationError. A Team's aggregate
19
+ failure remains a Phronomy::Error and now carries the stored code. An operation
20
+ that already succeeded with the same identity still replays its original result.
21
+ Unknown persistence outcomes and readback failures remain recovery requirements;
22
+ an inner code is not blindly copied onto that outer uncertainty.
23
+
24
+ The application may choose to retry only a durably failed planning attempt:
25
+
26
+ ```ruby
27
+ outcome && outcome[:status] == "failed" &&
28
+ outcome.dig(:error, "code") == "team.enqueue_after_finalize"
29
+ ```
30
+
31
+ Example 21 retains its four-section/content-length validator and existing retry
32
+ limit. That application policy is not part of the reason code contract.
33
+
34
+ ## Compatibility
35
+
36
+ No SQL columns or record-format versions change. Error diagnostics are content
37
+ JSON; the existing content codec carries the optional field without interpreting
38
+ it. Old diagnostics without codes remain readable. Unknown string codes are
39
+ preserved, and no code is inferred from a message.
40
+
41
+ A v0.28.0 reader can inspect the extra JSON field through stored result data.
42
+ Its reconstructed exceptions do not expose the new code, and paths that rebuild
43
+ a failure from class/message can lose it. Mixed-version writes and code-based
44
+ exception handling on an old reader are therefore unsupported. Upgrade consumers
45
+ before relying on codes; there is no automatic historical backfill.
data/docs/features.md CHANGED
@@ -30,6 +30,7 @@ for production deployments.
30
30
  | **Output Parser** — JSON and Struct-mapped parsers for structured LLM responses | Stable |
31
31
  | **Tracing** — Pluggable logical-operation span observability with bounded automatic coverage | Stable |
32
32
  | **Error Taxonomy** — Provider errors translated to Phronomy transport/authentication/rate-limit/context errors | Beta |
33
+ | **Optional failure reason codes** — `Phronomy::Error#code` and `code:` retain domain-supplied reasons in saved Agent/Team diagnostics; [meaning and compatibility](failure-reason-codes.md) | Beta |
33
34
 
34
35
  Agent definition lineage is separate from Agent instance identity. A named
35
36
  concrete Agent may declare `agent_definition version: N`; when `id:` is omitted,
@@ -46,18 +47,25 @@ rather than implicitly inheriting the parent revision. The Stable
46
47
  |---|---|
47
48
  | **Knowledge** — Journal-backed persistent Agent context registered with `knowledge:` / `add_knowledge`, selected per LLM call by Context Policy | Beta |
48
49
  | **`VectorStore#size`** — Document count for InMemory, RedisSearch, and Pgvector backends | Beta |
49
- | **VectorStore async convenience** — `add_async` / `search_async` / `remove_async` / `clear_async` offload the synchronous Backend SPI through Phronomy and return `TaskResult`; native async override is not part of the current Backend SPI | Beta |
50
- | **Embedding async convenience** — `embed_async` offloads synchronous `embed` through Phronomy and returns `TaskResult` | Beta |
50
+ | **Storage::AsyncClient** — `transaction_async` runs a raw backend transaction on one worker and returns TaskResult; [usage and lifetime rules](migrations/storage-async-client.md) | Beta |
51
+ | **VectorStore::AsyncClient** — `add_async` / `search_async` / `remove_async` / `clear_async` offload the synchronous Backend SPI through Phronomy and return `TaskResult`; native async override is not part of the current Backend SPI | Beta |
52
+ | **VectorStore::Embeddings::AsyncClient** — `embed_async` offloads synchronous `embed` through Phronomy and returns `TaskResult` | Beta |
51
53
  | **Model Context Protocol (MCP) Tool** — `Phronomy::Tools::Mcp` integration through the official `mcp` gem | Beta |
52
54
  | **Agent Tool** — `Phronomy::Tools::Agent.from_agent` exposes a child Agent as a Tool without occupying a worker while waiting | Beta |
55
+ | **Ordered event delivery** — Explicitly require `Phronomy::Integrations::OrderedEventDelivery` for bounded ordered delivery outside lifecycle callbacks; [lifetime and failure rules](ordered-event-delivery.md) | Beta |
53
56
  | **Vector Search Tool** — `Phronomy::Tools::VectorSearch` wraps VectorStore and Embeddings adapters | Beta |
54
57
 
58
+ Applications previously calling async methods on backend objects must
59
+ [move those calls to explicit clients](migrations/vector-async-clients.md).
60
+ Backend authors continue to implement the synchronous SPI only.
61
+
55
62
  ## Execution and reliability
56
63
 
57
64
  | Feature | Stability |
58
65
  |---|---|
59
66
  | **EventLoop** — Runtime-owned event-driven execution core shared by Agent, ToolInvocation, Workflow, and MultiAgent sessions; single writer for Phronomy-managed live Agent execution state | Beta |
60
67
  | **Agent execution result authority** — Session-local routing plus current FSM state and purpose-specific semantic IDs (`llm_call_id`, `tool_invocation_id`) reject stale async results | Beta |
68
+ | **Agent scope and unload** — `Agent.open_scope` owns newly acquired Agents; `unload_async` / `unload!` release idle incarnations without changing saved state, with typed invalidation and cleanup failures; [contract](architecture/dx05-agent-scope.md) | Beta |
61
69
  | **Agent live ownership/admission** — Runtime owns one mutable live Agent per `agent_id`; EventLoop rejects competing same-Agent top-level executions while suspension retains the logical execution slot; Persistence admission remains durable defense | Beta |
62
70
  | **Workflow durable admission** — Same-process admission is keyed by durable `workflow_instance_id` from pre-hydration admission through the durable terminal/halted save barrier; admission-owner representation is Runtime-internal | Beta |
63
71
  | **`invoke` / `invoke_async`** — Blocking and non-blocking Agent/Workflow entry points | Stable |
@@ -87,8 +95,8 @@ See the [migration guide](migrations/parallel-tool-chat-removal.md).
87
95
 
88
96
  | Feature | Stability |
89
97
  |---|---|
90
- | **Workflow asynchronous pattern** — Start async work, return immediately, and continue through `Workflow#signal` | Beta |
91
- | **Durable Handoff** — `Agent::Handoff` and `MultiAgent::HandoffRunner` persist responsibility, immutable Context and exact Target reservation in one Persistence domain; current graph wiring is required for continuation | Beta |
98
+ | **Workflow asynchronous pattern** — `task_state` starts a `TaskResult`, applies its successful value once to the current state entry, and then evaluates ordinary transitions; `Workflow#signal` remains the application event API | Beta |
99
+ | **Durable Handoff** — `MultiAgent::Handoff` and `MultiAgent::HandoffRunner` persist responsibility, immutable Context and exact Target reservation in one Persistence domain; current graph wiring is required for continuation | Beta |
92
100
  | **GeneratorVerifier** — Generator-Verifier loop with injectable prompts/parsers | Beta |
93
101
  | **`Phronomy::MultiAgent::Orchestrator`** — Parallel subagent dispatch, fan-out, and `subagent` DSL | Beta |
94
102
  | **`Phronomy::MultiAgent::TeamCoordinator`** — LLM coordinator with stateful worker Agents | Beta |
@@ -4,6 +4,11 @@ This guide contains the setup and introductory examples that were previously
4
4
  embedded in the repository README. The README remains the project entry point;
5
5
  this document carries the longer operational examples.
6
6
 
7
+ Blocks marked `ruby runnable` are complete after `require "phronomy"` and provider
8
+ configuration. Other blocks are setup or partial examples that reuse definitions
9
+ from the surrounding section. See [application recipes](application-recipes.md)
10
+ for independent examples and explicit failure handling.
11
+
7
12
  ## Install
8
13
 
9
14
  Add Phronomy to your Gemfile:
@@ -49,11 +54,9 @@ Install only the backend gems required by your application:
49
54
 
50
55
  ## Define a Tool and Agent
51
56
 
52
- Use `Phronomy::Tool::Base` as the application-facing authoring API. It is an
53
- exact alias of the existing `Phronomy::Agent::Context::Capability::Base`, so
54
- existing Tool definitions using the longer namespace remain compatible.
57
+ Use `Phronomy::Tool::Base` as the application-facing authoring API.
55
58
 
56
- ```ruby
59
+ ```ruby runnable
57
60
  class WebSearch < Phronomy::Tool::Base
58
61
  description "Search the web"
59
62
  param :query, type: :string, desc: "Search query"
@@ -85,7 +88,7 @@ application does not need to pass the previous `messages` array back into every
85
88
  invocation.
86
89
 
87
90
  ```ruby
88
- persistence = Phronomy::Persistence.in_memory
91
+ persistence = Phronomy::PersistenceComposition.agent
89
92
 
90
93
  agent = ResearchAgent.create(
91
94
  agent_id: "research-session-42",
@@ -115,7 +118,7 @@ A Runtime has at most one mutable live Agent object for an `agent_id`. If the
115
118
  Agent is already live, repeated `load` returns that exact Ruby object and does
116
119
  not reload Persistence. If it is not live, `load` hydrates the durable Agent
117
120
  once. Loading an ID that does not exist durably raises
118
- `Storage::NotFoundError`.
121
+ `Phronomy::Persistence::NotFoundError`.
119
122
 
120
123
  Use `get` when only a process-local lookup is wanted:
121
124
 
@@ -131,7 +134,7 @@ While the Agent is live, it owns its current AgentRoot/Journal view and
131
134
  Runtime/EventLoop owns process-local identity/admission/execution authority.
132
135
  Phronomy persists snapshots at defined durability boundaries but does not reload
133
136
  mutable Agent/Execution/Journal state before every LLM or Tool step. A conflicting
134
- external durable write is surfaced as `Storage::ConflictError` rather than
137
+ external durable write is surfaced as `Phronomy::Persistence::StateConflictError` rather than
135
138
  silently merged into the live instance.
136
139
 
137
140
  The active transcript and Knowledge views can be advanced independently without
@@ -165,7 +168,7 @@ the listener when the Agent is materialized, not on each invocation:
165
168
 
166
169
  ```ruby
167
170
  agent = ResearchAgent.load(
168
- "research-session-42",
171
+ "another-session-not-live-in-this-runtime",
169
172
  persistence: persistence,
170
173
  on_event: ->(event) {
171
174
  puts event.payload[:output] if event.type == :done
@@ -175,6 +178,10 @@ agent = ResearchAgent.load(
175
178
  task = agent.invoke_async("Hello")
176
179
  ```
177
180
 
181
+ This load assumes that the other Agent exists in Persistence but has not been
182
+ materialized in this Runtime. To listen to `research-session-42`, register its
183
+ listener in the original `create` call.
184
+
178
185
  `new`, `create`, and `load` also accept an equivalent listener block.
179
186
  Supplying both `on_event:` and a construction block is an error. If `load`
180
187
  resolves an already-live same-process Agent, supplying any new listener/block
@@ -250,7 +257,7 @@ end
250
257
  write_draft = ->(state) { state.merge(draft: "Draft content") }
251
258
  review_draft = ->(state) { state.merge(feedback: "Feedback on: #{state.draft}") }
252
259
 
253
- persistence = Phronomy::Persistence.in_memory
260
+ persistence = Phronomy::PersistenceComposition.in_memory.workflow
254
261
 
255
262
  workflow = Phronomy::Workflow.define(
256
263
  ReviewContext,
@@ -274,7 +281,7 @@ final = workflow.send_event(state: state, event: :approve)
274
281
  puts final.approved
275
282
  ```
276
283
 
277
- `Persistence#workflow_states` is the durable Workflow repository. `workflow_instance_id`
284
+ The injected Workflow checkpoint repository supplies `load`, `save`, and `delete`. `workflow_instance_id`
278
285
  identifies the durable Workflow state and remains stable across resume. Each
279
286
  concrete Runtime execution receives a separate internal `fsm_session_id`; the
280
287
  application-level `session_id` remains ordinary caller/tracing metadata. Phronomy
@@ -286,28 +293,29 @@ A global Persistence backend can be configured when Agents and Workflows should
286
293
  share one durable backend:
287
294
 
288
295
  ```ruby
296
+ stores = Phronomy::PersistenceComposition.in_memory
289
297
  Phronomy.configure do |config|
290
- config.persistence = persistence
298
+ config.agent_store = stores.agent
299
+ config.multi_agent_store = stores.multi_agent
300
+ config.workflow_store = stores.workflow
291
301
  end
292
302
  ```
293
303
 
294
- Agent `new`/`create` and Workflow definitions use the global backend when they do
304
+ Agent `new`/`create`, Team construction, and Workflow definitions use their configured store when they do
295
305
  not inject an explicit `persistence:`. Workflow durability is fixed at the
296
306
  application/Workflow-definition boundary; there is no per-invocation backend
297
307
  switch.
298
308
 
299
- Workflow entry and transition actions are synchronous Run-to-Completion
300
- callbacks. If a Workflow needs an Agent or another asynchronous lifecycle, start
301
- it asynchronously, return the Workflow context immediately, and deliver its
302
- completion later with `Workflow#signal`.
309
+ Use `task_state` when a state starts an asynchronous operation and needs its
310
+ terminal result before proceeding. `start` returns the TaskResult immediately;
311
+ `apply` updates the current Workflow context on EventLoop. Guards run after
312
+ successful application. Ordinary entry and transition actions remain synchronous.
303
313
 
304
- ```ruby
314
+ ```ruby runnable
305
315
  class AnswerContext
306
316
  include Phronomy::WorkflowContext
307
-
308
317
  field :question, type: :replace, default: ""
309
- field :answer, type: :replace, default: nil
310
- # workflow_instance_id is framework-owned metadata; do not declare it as a field.
318
+ field :answer, type: :replace, default: nil
311
319
  end
312
320
 
313
321
  class ResearchAgent < Phronomy::Agent::Base
@@ -317,40 +325,35 @@ class ResearchAgent < Phronomy::Agent::Base
317
325
  end
318
326
 
319
327
  my_agent = ResearchAgent.new
320
- workflow = nil
321
-
322
328
  workflow = Phronomy::Workflow.define(AnswerContext) do
323
329
  initial :asking
324
- state :asking
325
- state :done
326
-
327
- entry :asking, ->(ctx) {
328
- workflow_instance_id = ctx.workflow_instance_id
330
+ task_state :asking,
331
+ start: ->(state) { my_agent.invoke_async(state.question) },
332
+ apply: ->(state, result) { state.merge(answer: result.fetch(:output)) }
333
+ transition from: :asking, to: :__finish__
334
+ end
329
335
 
330
- my_agent.invoke_async(ctx.question) do |event|
331
- next unless event.type == :done
336
+ answer = workflow.invoke(
337
+ {question: "What is an asynchronous completion handle?"},
338
+ config: {workflow_instance_id: "answer-example"}
339
+ )
340
+ puts answer.answer
341
+ ```
332
342
 
333
- workflow.signal(
334
- workflow_instance_id: workflow_instance_id,
335
- event: :answer_ready,
336
- payload: {answer: event.payload[:output]}
337
- )
338
- end
343
+ Phronomy correlates completion to this execution and state entry, ignores stale
344
+ results after exit or reentry, and propagates start/source/apply failures to the
345
+ caller. A cancelled source cancels the Workflow observation; a failed source
346
+ retains its failure classification. External business events still use
347
+ `Workflow#signal` or `send_event`.
339
348
 
340
- ctx
341
- }
342
-
343
- transition(
344
- from: :asking,
345
- on: :answer_ready,
346
- to: :done,
347
- action: ->(ctx, event) { ctx.merge(answer: event.payload[:answer]) }
348
- )
349
- end
350
- ```
349
+ `task_state` is a live wait, while `wait_state` halts the current execution segment.
350
+ Pending Tasks are not persisted: attempting to restore a task-state snapshot
351
+ raises `WorkflowTaskResumeError`. Normal wait-state halt/resume remains supported.
352
+ Parent cancellation stops application of the result; cancelling the child itself
353
+ requires explicit controls passed by the application. See the
354
+ [task-state contract](architecture/dx05-workflow-task-state.md) for these boundaries.
351
355
 
352
- Returning a `Phronomy::TaskResult` from a Workflow entry/transition action is not an
353
- implicit await mechanism and is rejected.
356
+ Returning a TaskResult from an ordinary entry/transition action remains an error.
354
357
 
355
358
  ## Agent as Tool
356
359
 
@@ -432,6 +435,7 @@ contracts.
432
435
  ## Next steps
433
436
 
434
437
  - [Features and API stability](features.md)
438
+ - [Application recipes](application-recipes.md)
435
439
  - [Runtime and concurrency](runtime-and-concurrency.md)
436
440
  - [Architecture decisions](decisions/)
437
441
  - [Migration guides](migrations/)
@@ -178,8 +178,8 @@ and no ordinary Handoff Tool result is generated.
178
178
 
179
179
  ACS-04 replaces the intermediate Context selection composition API with the
180
180
  final four-category Context Policy SPI. Application-defined policies receive an
181
- immutable `Phronomy::Agent::ContextPolicyInput` and return an immutable
182
- `Phronomy::Agent::ContextPlan`, each organized as `instruction`, `knowledge`,
181
+ immutable `Phronomy::Context::ContextPolicyInput` and return an immutable
182
+ `Phronomy::Context::ContextPlan`, each organized as `instruction`, `knowledge`,
183
183
  `tools`, and grouped `conversation`.
184
184
 
185
185
  Agent classes bind one Application-constructed Policy instance:
@@ -1,5 +1,7 @@
1
1
  # Durable semantic coordination V2 migration
2
2
 
3
+ > r8 unit 4 supersedes the Agent/Handoff ownership and storage portions below. See [the unit 4 migration](../migrations/r8-unit4.md). Earlier statements describe their original change only.
4
+
3
5
  > Runner namespace update (2026-09-18): this document preserves the V2
4
6
  > implementation/migration record. The current Runner is
5
7
  > `Phronomy::MultiAgent::HandoffRunner` under
@@ -1,5 +1,7 @@
1
1
  # HandoffRunner moves to MultiAgent
2
2
 
3
+ > r8 unit 4 supersedes the Agent/Handoff ownership and storage portions below. See [the unit 4 migration](../migrations/r8-unit4.md). Earlier statements describe their original change only.
4
+
3
5
  This change applies to H1 on `refactor/architecture` after core commit
4
6
  `fe2ad7cea6945a240858b18645dc4ae285e8ce64`. The released 0.26.0 gem does not
5
7
  yet provide this new Runner name.
@@ -0,0 +1,67 @@
1
+ # Migrate the domain Persistence failure contract
2
+
3
+ This change intentionally changes the exception classes exposed by domain
4
+ Persistence operations. Apply it together with application rescue-clause updates;
5
+ there is no compatibility alias. Public method arguments, return values and
6
+ backend SPI 2 do not change.
7
+
8
+ ## Application and domain repository callers
9
+
10
+ For calls through `Persistence`, its eight repositories, Agent, Team and Workflow,
11
+ use the upper contract:
12
+
13
+ | Previous category | New category |
14
+ |---|---|
15
+ | `Phronomy::Storage::ConflictError` | `Phronomy::Persistence::ConflictError` |
16
+ | `Phronomy::Storage::NotFoundError` | `Phronomy::Persistence::NotFoundError` |
17
+ | `Phronomy::Storage::SerializationError` | `Phronomy::Persistence::SerializationError` |
18
+ | `Phronomy::Storage::UnsupportedBackendError` | `Phronomy::Persistence::UnsupportedBackendError` |
19
+
20
+ For example:
21
+
22
+ ```ruby
23
+ begin
24
+ root = persistence.agents.load(agent_id)
25
+ rescue Phronomy::Persistence::NotFoundError => error
26
+ # Handle the missing domain object here.
27
+ logger.info(error.message)
28
+ end
29
+ ```
30
+
31
+ `Persistence::StateConflictError < Persistence::ConflictError` identifies state,
32
+ ownership or revision contradictions raised by upper domain operations. Catch
33
+ ConflictError when the application handles both state and backend conflicts.
34
+ This subtype is not an instruction to retry: retain operation-specific retry and
35
+ recovery policies. Repository CAS/precondition rejections expose ConflictError.
36
+
37
+ Translated backend failures retain their original message/backtrace and expose
38
+ the original exception through `error.cause`. Backend constraint/resource details
39
+ remain there. `AgentBusyError` keeps its existing meaning and original cause;
40
+ only the owning active constraint/condition qualifies for that mapping.
41
+
42
+ ## Backend implementations and raw callers
43
+
44
+ Do **not** globally replace Storage exception names in driver implementations or
45
+ raw `Storage::Backend`/View/Records/Streams/Blobs callers. Those interfaces still
46
+ raise Storage errors. The raw `persistence.backend` accessor exposes that same
47
+ backend. Direct `ContentStore::StoredContents` use also retains its raw failure
48
+ surface; `persistence.contents` applies the upper translation boundary.
49
+
50
+ Core domain repository conformance examples now expect Persistence errors. Raw
51
+ Storage conformance examples continue to expect Storage errors. Tests which
52
+ inject failures at the physical backend should still inject Storage exceptions;
53
+ tests mocking an already translated repository should inject Persistence errors.
54
+
55
+ ## Commit uncertainty and saved data
56
+
57
+ Only the four listed categories are translated. Unknown driver/transport errors,
58
+ including IOError, and Storage::TransactionError pass through as the same object.
59
+ ContentStore::IntegrityError and existing domain errors also retain identity.
60
+ Do not classify every Persistence::Error as a known rollback, and do not add a
61
+ retry for a lost commit acknowledgement. Existing admission, transaction scope,
62
+ rollback, nested savepoint and recovery rules continue to apply.
63
+
64
+ No database migration is required. Saved records and content bytes use the same
65
+ formats. Error class names in newly saved diagnostic payloads can use the new
66
+ Persistence names. Old saved class strings remain diagnostic data; they are not
67
+ resolved as live exception constants or rewritten.
@@ -0,0 +1,36 @@
1
+ # Migrating to r8 unit 10
2
+
3
+ Apply after core d961fc742f6c4ea4d06dc89f20eedfeb49d04099 (unit 9).
4
+ This package changes core only. The unit 6 examples at
5
+ ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
6
+
7
+ Public TeamCoordinator and HandoffRunner arguments and results are unchanged.
8
+ No database migration or application Registry registration is needed.
9
+ The existing registries remain MultiAgent-owned and preserve their rules.
10
+
11
+ | Internal use | Replacement |
12
+ | --- | --- |
13
+ | AdmissionRegistry.for(runtime) | The owning MultiAgent ExecutionEnvironment.admissions |
14
+ | TeamOwnershipRegistry.for(runtime) | The owning environment.ownership |
15
+ | TeamOwnershipRegistry.existing_for(runtime) | The selected environment.existing_ownership for lookup only |
16
+ | Team/Handoff Runtime.instance checks | The captured environment.current? |
17
+ | Team cancellation Execution.submit(runtime: ...) | The captured environment.submit(...) |
18
+ | Team persistence factory in runtime_composition/agent_defaults.rb | runtime_composition/multi_agent_defaults.rb |
19
+
20
+ Registry construction remains side-effect free. Tests of domain rules can use
21
+ Registry.new; tests of Runtime registration use MultiAgent::EngineEnvironment.
22
+ Removed private class methods have no aliases. Internal callers are updated
23
+ together. New connection classes are private APIs; public RBS signatures stay
24
+ unchanged. Ordinary require "phronomy" installs defaults lazily, without creating
25
+ global configuration, stores or a Runtime during loading.
26
+
27
+ The ZIP includes complete changed files, a strict-base applier, expected-tree
28
+ verification, a review patch, test evidence and rollback instructions. Run
29
+ --check, --apply and --verify in a new worktree, then --verify again after commit.
30
+ Use the existing stop/drain procedure when replacing running processes. This
31
+ change does not add in-flight cross-version compatibility or rollback of
32
+ external effects.
33
+
34
+ For examples verification, unset BUNDLE_GEMFILE before entering the examples
35
+ checkout and set PHRONOMY_PATH to the candidate core. Inspect and restore only
36
+ verification-generated lockfile/vendor changes; no examples commit is needed.