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,115 @@
1
+ # r8 unit 5: VectorStore and Embeddings common contracts
2
+
3
+ Core baseline: `29818f5d0577ac5287c5429d6d169ef5fd1c0225`.
4
+ Examples baseline: `c410fc88112ad5e4648ba2e51335023885d9373b`.
5
+ The contract concept and foundation target remain the design goal. This unit
6
+ implements C10/C11 common operation ownership and DP09/DP10 placement. It does
7
+ not complete the other domain Contracts or the outstanding unit 4 acceptance gates.
8
+
9
+ ## Ownership and completion conditions
10
+
11
+ Contract membership follows domain semantics, not frequency of reuse. A Contract
12
+ defines its domain's concepts, legal inputs/results, invariants, extension points
13
+ and observable failure/operation rules. Its framework executes those rules.
14
+ Code used by several callers is not automatically a Contract; a generic utility,
15
+ concrete adapter helper or composition operation can have several callers too.
16
+
17
+ | Placement decision in this unit | Domain reason |
18
+ | --- | --- |
19
+ | VectorStore id/vector/metadata inputs and ordered search results | These describe the public vector storage/retrieval operation independently of a database |
20
+ | Embeddings text/vector inputs and results | These describe text embedding independently of the provider SDK and downstream storage |
21
+ | Validation, pre-operation cancellation checkpoint and InvalidResultError | These enforce the operation's observable invariants and failure rules |
22
+ | Float-array normalization | This realizes the declared vector representation; it does not make arbitrary serialization a Contract concern |
23
+ | Redis RESP2 decoding, distance-to-similarity conversion, Pgvector row/JSON decoding | These are concrete backend adaptations and remain in the corresponding backend |
24
+ | Document loading/splitting | These are document utilities separated from VectorStore; this move does not create a new Contract |
25
+ | Async submission and timeout settlement | These remain Execution responsibilities, connected through each AsyncClient |
26
+
27
+ | Responsibility | Owner | Completion evidence |
28
+ | --- | --- | --- |
29
+ | Vector operation entry, cancellation checkpoint, input/result validation, chaining | `VectorStore::Base` | A hook-only custom backend receives validated inputs; malformed inputs perform no I/O; malformed outputs fail explicitly |
30
+ | Search/storage algorithms, physical dimension state, database encoding | `VectorStore::{InMemory,Pgvector,RedisSearch}` | Existing algorithm and adapter tests run through inherited public operations |
31
+ | Text input and finite embedding result validation | `Embeddings::Base` | A hook-only provider works without SDK, Engine or VectorStore; malformed outputs are rejected |
32
+ | Embedding provider call and SDK exception translation | `Embeddings::RubyLLMEmbeddings` | Provider exceptions retain their cause; cancellation and application failures retain their identity |
33
+ | Submission, timeout, admission and completion handle | Each feature's `AsyncClient` and Execution | Existing pool, cancellation, timeout and Runtime reset tests |
34
+ | Document input and splitting | `Documents::Loader` / `Documents::Splitter` | Existing document tests; no VectorStore or Embeddings dependency |
35
+
36
+ Common behavior lives in the existing Base classes. There is no forwarding
37
+ Contract, Base-to-client factory, compatibility alias or mandatory embedding
38
+ provider in VectorStore. Protected `perform_*` methods are the extension SPI;
39
+ applications call the inherited public operations. Ruby can override any method,
40
+ but overriding the public template is outside the documented backend SPI.
41
+
42
+ ## Defined operation behavior
43
+
44
+ `VectorStore#add` checks cancellation, a String id, Hash metadata, a vector of
45
+ finite real numbers and the backend's known dimension before entering the
46
+ storage hook. It supplies a fresh Float array and returns the store. `remove`
47
+ and `clear` also return the store. A search validates input and positive `k`
48
+ before entering its hook, including an empty Redis store. Decimal strings for
49
+ `k` remain supported; fractional values no longer truncate silently.
50
+
51
+ Search results must be an Array of at most `k` Hashes with String `:id`, finite
52
+ numeric `:score`, Hash `:metadata`, and descending score order. A count must be
53
+ a non-negative Integer. Violations raise `VectorStore::InvalidResultError`.
54
+ Backend transport failures propagate without retries. Redis count failures no
55
+ longer become a successful zero count. Backend-specific index creation, metadata
56
+ encoding and query construction remain in the backend; they are not new common
57
+ storage primitives. Existing dimension-zero InMemory vectors remain supported.
58
+
59
+ Backends must not invent successful values while decoding malformed external
60
+ responses. RedisSearch validates its RESP2 count, field pairs, document keys,
61
+ numeric distances and JSON object metadata before producing the public result.
62
+ A genuine zero-match reply is `[0]`. A missing whole reply is invalid. Redis's
63
+ documented null document contents after expiration/update are omitted; they do
64
+ not imply a corrupt response, and the total can exceed the returned page size.
65
+ Missing/null Redis metadata and a SQL NULL metadata column still mean empty
66
+ metadata. Invalid JSON text, empty JSON text, JSON scalars/arrays and invalid
67
+ scores raise `InvalidResultError`. Pgvector also rejects invalid row ids rather
68
+ than turning them into strings. JSON parse failures preserve their original cause;
69
+ transport/database exceptions propagate unchanged and no read is retried.
70
+
71
+ The response decoders stay private to each backend. Base does not know Redis
72
+ commands, RESP versions, ActiveRecord rows, JSON columns or SDK exceptions.
73
+ The existing RESP2 support boundary and known-dimension/index initialization
74
+ requirements remain; this unit does not add RESP3 support.
75
+
76
+ Protocol references: [FT.SEARCH](https://redis.io/docs/latest/commands/ft.search/)
77
+ and [FT.INFO](https://redis.io/docs/latest/commands/ft.info/), checked 2026-10-03.
78
+
79
+ `Embeddings#embed` checks cancellation and String input, invokes `perform_embed`
80
+ once, and validates a non-empty finite vector before returning Float values.
81
+ Malformed output raises `Embeddings::InvalidResultError`. The RubyLLM backend
82
+ translates `RubyLLM::Error` to `Embeddings::TransportError`, preserving `cause`.
83
+ This error does not imply that external work was or was not accepted. There is
84
+ no automatic retry and no classification of an arbitrary application exception
85
+ as a provider failure.
86
+
87
+ Cancellation is cooperative. The common checkpoint occurs before the backend
88
+ operation; a provider may inspect the same signal during its work. A successful
89
+ write is not changed into cancellation by a post-write check. Timeout and result
90
+ settlement remain Execution responsibilities; an external call may continue.
91
+
92
+ Input errors are F0 failures before X0 I/O. For a write that has crossed X0,
93
+ failure/timeout is not proof of a rollback or of a missing external effect.
94
+ This unit adds no F1 outcome reconciliation, F4 recovery, cross-process exclusion
95
+ or exactly-once external-effect guarantee. InMemory dimension inference and
96
+ backend concurrency constraints retain their documented limits.
97
+
98
+ ## Refactoring completion tracking
99
+
100
+ | Contracts | Current boundary status | Remaining work |
101
+ | --- | --- | --- |
102
+ | C10 VectorStore / C11 Embeddings | Common contract behavior implemented in unit 5 | Real Pgvector/Redis/provider service verification remains an implementation gate, reported separately |
103
+ | C05 Context / C07 Persistence / C08 ContentStore / C12 Storage / C13 Execution / C15 Tracing | Main common foundations implemented in units 1-4 | Additional domain acceptance conditions and overall dependency review are not waived |
104
+ | C09 LLM / C06 Tool | Partial | Public values/failures, SDK-neutral operation boundary, Tool SDK inheritance and execution connection |
105
+ | C04 Agent / C01 MultiAgent | Unit 4 ownership boundary implemented | FSM/Runtime/composition dependencies |
106
+ | C02 Workflow | Partial | FSM connection and durable child identity/resume/outcome reconciliation |
107
+ | C03 Generation / C16 Filter / C17 OutputParser | Existing common implementation | Finish responsibility-level conformity review; absence of certification is not evidence that all code is missing |
108
+
109
+ Next implement C09/C06 together where their SDK boundary interacts, then finish
110
+ C04/C01/C02 execution connections and durable collaboration. Inspect the existing
111
+ C03/C16/C17 implementations against explicit conditions before scheduling rewrites.
112
+
113
+ The package records commands actually executed and unexecuted backend gates.
114
+ See [migration](../migrations/r8-unit5.md) and
115
+ [ADR-065](../decisions/065-vector-and-embeddings-common-operations.md).
@@ -0,0 +1,71 @@
1
+ # r8 unit 6: C09 LLM and C06 Tool
2
+
3
+ Contract placement is determined by ownership of meaning and operations. Reuse
4
+ alone is not a reason to put code into a contract. This unit completes the scoped
5
+ LLM/Tool operation boundary; it does not complete every contract in the target.
6
+
7
+ | Owner | Meaning and operations |
8
+ | --- | --- |
9
+ | C09 LLM, `LLMAdapter` | Immutable Request, Message, Response, StreamChunk and TokenUsage; complete/stream templates; input/result/cancellation checks; public failures |
10
+ | C06 Tool, `Tool` | CallRequest, declarations, advertised schema, argument validation/coercion, authorization evaluation and execution/error rules |
11
+ | RubyLLM backend | SDK chat construction, options, message/Tool rendering, chunk/response decoding, SDK exception translation and SDK Tool interception |
12
+ | Agent | Select context, prepare executable Tools, run approval and Tool batches, consume LLM results, persist and recover execution facts |
13
+ | Execution / AsyncClient | Scheduling, cancellation signals, deadlines and worker submission; AsyncClient submits the whole LLM operation |
14
+
15
+ Tool requests are ordinary assistant Response values. They do not authorize or
16
+ execute a Tool. Only the backend knows RubyLLM's message callback and its private
17
+ interception signal. SDK Tool declarations have a rejecting execute method; an
18
+ accidental SDK auto-execution fails instead of bypassing Agent authorization.
19
+ A minimal backend needs only protected perform_complete/perform_stream hooks.
20
+ Agent does not require a Chat-like object, SDK methods or executable Tool handles
21
+ from it. Streaming returns a final Response in addition to typed chunk events.
22
+
23
+ TokenUsage and the four existing LLM failures move from the root namespace into
24
+ LLMAdapter, with no aliases. Unknown usage remains nil, distinct from zero.
25
+ ContextLengthError remains a direct Phronomy::Error; rate limiting and
26
+ authentication remain TransportError subtypes. InvalidResultError identifies
27
+ malformed results rather than a valid empty response. SDK errors retain cause;
28
+ application callback errors and cancellation retain their original identity.
29
+
30
+ `Tool::Base` no longer inherits RubyLLM::Tool. Both `param` and explicit `parameters`
31
+ (Hash/schema DSL) produce a C06 Schema. `validate_arguments` is the public, pure
32
+ preflight operation used before approval; `call` uses the same schema/rules before
33
+ execute. Legacy private type/coercion/nesting algorithms are removed. Parameters
34
+ that were advertised but not enforced by the explicit-schema path now fail before
35
+ approval or execute. See the migration document for the supported schema dialect.
36
+
37
+ SDK initialization, setters, completion and decoding run within AsyncClient's
38
+ worker operation. Cancellation is checked before and after the backend operation,
39
+ after SDK construction, and before delivering chunks. A deadline is an Execution
40
+ cancellation signal. It can settle the caller while a blocking SDK constructor is
41
+ still running; it does not forcibly stop a thread. When that constructor returns,
42
+ the cancellation checkpoint prevents starting a new provider request. Already
43
+ sent external work is not rolled back. Local input_budget uses existing model
44
+ registry metadata; live capacity discovery is not added to the contract.
45
+
46
+ Saved context materializes Phronomy Message/CallRequest values. SDK rendering
47
+ occurs later inside the backend, including structured-content JSON rendering and
48
+ opaque thought_signature metadata. Existing durable thought_signature and usage
49
+ field spellings remain readable. New Tool batch metadata stores the validated
50
+ argument snapshot alongside raw arguments so public authorization projection
51
+ compares what was approved, including coercion and intentional null. Historical
52
+ snapshots retain their explicit old decoding rule. Recovery resolution accepts a Response or its
53
+ canonical Hash, not arbitrary SDK objects. Record identities, transaction/CAS
54
+ rules, approval ownership and F0/F1/F4 classifications remain with Agent and
55
+ Persistence. No exactly-once or automatic retry guarantee is introduced.
56
+
57
+ ## Architecture evidence
58
+
59
+ M47 (`llm_contract`) is retired into M15 (`llm_adapter`); the identifier is not
60
+ reused and historical diagrams remain historical. C09 is allowed to reference
61
+ C06 Schema/CallRequest. Directory aggregation also shows C09 -> Tool -> Execution,
62
+ because Tool::Base owns an execution template in the same directory as the values.
63
+ The directory gate permits that specific route; AST checks reject direct C09
64
+ mechanism references, Tool::Base consumption and SDK/Agent/Engine leaks. The full
65
+ Ruby/RBS matrix retains the route instead of hiding it. Standalone loading and a
66
+ minimal backend execution test additionally establish that C09 values do not
67
+ load Tool::Base, Agent, Engine or the SDK.
68
+
69
+ Remaining work includes Agent/MultiAgent/Workflow FSM and Runtime connections,
70
+ Workflow durable children and cross-record outcome evidence, live provider
71
+ verification, and the broader semantic review of existing dependency triangles.
@@ -0,0 +1,70 @@
1
+ # r8 unit 7: C04 Agent progress and execution connection
2
+
3
+ Contract placement follows ownership of meaning, invariants, operations and
4
+ failures. It is not determined by reuse. This unit improves C04; it does not mark
5
+ all of C04, C06 or the overall target complete.
6
+
7
+ | Owner | Responsibility after this change |
8
+ | --- | --- |
9
+ | Agent InvocationTransitions | Phase vocabulary, ordered automatic/external transitions, guard evaluation, iteration bound |
10
+ | Agent InvocationActions | Prepared input, LLM dispatch, Tool batch orchestration and result/event interpretation |
11
+ | Agent ExecutionCoordinator / RecoveryCoordinator | Admission, durable preparation, approval, terminal outcome, recovery and causal revision checks |
12
+ | Agent ExecutionEnvironment | Private process-local connection required by the Agent framework; session construction/registration, serial owner and operation submission |
13
+ | Agent EngineEnvironment / EngineSessionBuilder / PhaseMachineBuilder | Runtime registration, EventLoop channel, FSMSession construction and state_machines adaptation |
14
+ | ExecutionReceiver | Serial-owner admission, delivery and lifecycle framework for feature-owned live state |
15
+ | Engine ExecutionReceiverBinding | Concrete EventLoop registration, locking, queued delivery and routing |
16
+
17
+ Previously AgentInvocationSessionBuilder combined Agent entry operations with
18
+ FSMSession creation. PhaseMachineBuilder held automatic progress rules, while
19
+ InvocationTransitions held only external transitions. Execution/recovery also
20
+ selected Runtime.instance repeatedly. The split now leaves both transition sets
21
+ and their priority with Agent. The Engine builder only installs those definitions
22
+ and synchronous entry callbacks into state_machines. InvocationActions retains
23
+ Agent semantics instead of moving the old class wholesale into an adapter.
24
+
25
+ An Agent captures the environment of its ownership registry at construction.
26
+ Execution and recovery reuse it; changing the composition provider does not move
27
+ a live Agent to another Runtime. Cancellation records its durable request before
28
+ posting a notification through that same environment, including after a provider
29
+ change. Detached Agent cancellation is rejected by the existing live-owner check.
30
+ The default provider is installed lazily by runtime_composition/agent_defaults.rb.
31
+ This is an internal composition port, not a new supported application plugin API.
32
+
33
+ ExecutionRegistry remains Agent-owned. Its generic serial receiver framework
34
+ moves from Engine to Execution and receives a channel. The actual EventLoop
35
+ transport stays in Engine. WorkflowExecutionRegistry uses that same channel to
36
+ preserve its existing receiver lifecycle; Workflow policy is not migrated here.
37
+ This placement follows ownership of execution admission/lifecycle, not merely
38
+ that Agent and Workflow share a base class.
39
+
40
+ Provider Call identity is passed explicitly to AgentInvocation from the already
41
+ prepared durable execution. AgentInvocation no longer queries global Runtime to
42
+ find it. FSMSession IDs remain ephemeral routing incarnation IDs. Approval and
43
+ recovery create a fresh session while preserving durable execution/LLM/Tool IDs.
44
+ No storage schema, CAS revision, parent admission, atomicity or F0/F1/F4 policy
45
+ changes. External effects are not exactly-once. Cancel/timeout do not forcibly
46
+ stop workers or undo effects; terminal persistence still waits for physical
47
+ quiescence. Stale session/revision results remain rejected on the serial owner.
48
+
49
+ ## Evidence and limits
50
+
51
+ The tests execute the transition policy in a standalone Ruby process without
52
+ Engine or state_machines, enumerate all 32 Tool outcome priority combinations,
53
+ compare the Engine adapter's behavior, and check environment retention and
54
+ cancellation routing. Existing recovery, approval, callback failure, single-writer,
55
+ stale-result and shutdown tests remain part of full/integration validation.
56
+ An AST gate rejects concrete Engine constants and state_machines loading in Agent
57
+ execution, recovery, lifecycle and ExecutionEnvironment. This is a scoped gate,
58
+ not proof that every dependency in the system is correct.
59
+
60
+ The measured graph adds M88/G62 for agent/runtime_binding; retired IDs are not
61
+ reused. Ruby and RBS references remain in the evidence, including cycles caused
62
+ by other uncompleted boundaries. Regenerate the measured diagram from the exact
63
+ candidate; do not treat it as the acyclic target design.
64
+
65
+ Still pending: Agent's Tool child FSM/session builder and its Runtime selection;
66
+ MultiAgent and Workflow FSM/Runtime connections; Workflow durable children and
67
+ cross-record outcome evidence; broader dependency-triangle review. The C06 Tool
68
+ operation/schema contract established in unit 6 remains intact, but its Agent-side
69
+ execution connection is not declared complete by this unit. LLM AsyncClient's
70
+ execution backend selection also remains the existing C09/C13 composition.
@@ -0,0 +1,78 @@
1
+ # r8 unit 8: C04 Tool child progress and C06 operation boundaries
2
+
3
+ Contract placement follows ownership of domain meaning, invariants and operations.
4
+ C04 owns the lifecycle of a Tool invocation inside an Agent. Calling a Tool does
5
+ not transfer that lifecycle to C06. This unit completes the scoped Tool child FSM
6
+ separation left by unit 7; it does not certify all of C04 or the overall target.
7
+
8
+ | Owner | Responsibility |
9
+ | --- | --- |
10
+ | Agent ToolInvocationTransitions | Child phases, ordered automatic/external transitions, legal event sources and recursion bound |
11
+ | Agent ToolInvocationActions / ToolInvocation | Validation/authorization orchestration, approval waiting, dispatch eligibility, outcome application and parent notification |
12
+ | Agent ExecutionEnvironment | The original Agent connection for authorization and default Tool submissions, operation supervision and session creation |
13
+ | Agent ToolSessionBuilder / PhaseMachineBuilder in runtime_binding | Concrete FSMSession/EventSink construction and state_machines adaptation of Agent-owned rules |
14
+ | Tool Operation | Tool execution-mode validity, standard/custom async operation dispatch, completion protocol and result adaptation |
15
+ | Tool ToolExecutor | Default cooperative/offloaded Tool operation, using the injected C13 submission protocol |
16
+ | Execution / _ExecutionSubmitter | Execution submission and completion semantics; concrete resource selection stays in the supplied connection |
17
+
18
+ ## What changed
19
+
20
+ ToolInvocationSessionBuilder previously repeated external transitions in both its
21
+ event map and state_machines DSL while also constructing sessions and executing
22
+ Agent entry operations. The new child policy owns one immutable transition set.
23
+ The concrete phase machine and FSMSession source admission read that set. The
24
+ existing parent FSM adapter accepts a policy, so no second domain-aware FSM
25
+ implementation is introduced. Entry operations remain executable Agent code.
26
+
27
+ ToolInvocation now requires its owning execution environment for authorization
28
+ and execution. It no longer selects Runtime.instance, inspects EventLoop, creates
29
+ an ExecutionRegistry connection or selects ToolExecutor. The parent Agent and
30
+ recovery already retain the environment from unit 7; the same environment now
31
+ supplies Tool child entry operations. Authorization captures immutable command
32
+ data before submission. Worker completion delivers an outcome, and serial event
33
+ delivery applies live state.
34
+
35
+ Tool::Operation.call_async is the C06 operation entry for composition-aware
36
+ callers. It selects the standard or custom Tool protocol and validates the
37
+ execution mode and completion handle. Its submitter must implement C13 submit;
38
+ it receives no Agent-specific type. The default offloaded path uses the supplied
39
+ connection, while cooperative work executes inline without a worker. Custom
40
+ call_async implementations keep their existing keyword signature and config,
41
+ return their original handle and continue to own their execution mechanism.
42
+ In particular, an override that calls super still uses the existing Base
43
+ protocol; this change does not inject hidden Runtime state into overrides.
44
+
45
+ Tool::Operation.with_result_transform owns the synchronous/custom-async Tool
46
+ decoration mechanism formerly embedded in Agent::ToolBinding. Agent still chooses
47
+ its configured filters and their meaning. Custom async mapping uses
48
+ AsyncOperation.map and preserves physical completion after logical cancellation.
49
+ As before, an override that itself calls an already decorated synchronous method
50
+ can transform twice; this unit does not rewrite arbitrary application overrides.
51
+
52
+ ## Preserved behavior and limits
53
+
54
+ Authorization completion keeps cancelled > failed > rejected > approval wait >
55
+ authorized priority. Execution completion keeps cancelled > failed > completed.
56
+ Validation keeps failure > completed schema handling > authorization. Explicit
57
+ approve/reject/dispatch/cancel events keep their legal source phases.
58
+ Start execution still precedes mark_running!, preserving dispatch eligibility.
59
+
60
+ Approval/recovery create fresh FSMSession routing IDs while retaining durable
61
+ execution, Tool call and invocation IDs. Parent sinks are session-local. This
62
+ change does not alter persistence schema, CAS revisions, approval snapshots,
63
+ causal dispatch preparation, stale-result handling, single-writer ownership or
64
+ terminal persistence after physical quiescence. Cancellation/timeout do not undo
65
+ external effects or forcibly stop workers; exactly-once effects are not promised.
66
+
67
+ The new tests cover all 48 child guard combinations, legal event sources,
68
+ standalone policy loading without Engine/state_machines, worker-result isolation,
69
+ owning-environment submission, fresh recovery routing, custom call_async and
70
+ physical-completion-aware result transformation. Existing parent transition,
71
+ approval, recovery and shutdown suites remain acceptance gates. The AST gate now
72
+ also rejects concrete Engine/FSM references and ToolExecutor selection in Agent
73
+ tool_execution. Static gates are scoped; they do not prove every dependency valid.
74
+
75
+ MultiAgent/Workflow FSM and Runtime connections, Workflow durable children,
76
+ other concrete composition choices, overall dependency review and additional
77
+ live-service/persistence acceptance tests remain. Regenerate the measured graph
78
+ from the exact candidate; target diagrams are not measured dependency evidence.
@@ -0,0 +1,73 @@
1
+ # R8 unit 9: preserve application-defined Tool result transformations
2
+
3
+ ## Ownership
4
+
5
+ The application owns which transformations run, their order and their
6
+ multiplicity. Agent's ToolBinding captures and composes its configured filters.
7
+ C06 Tool owns the operation/decorator mechanism that executes that composition.
8
+ C13 Execution owns completion adaptation, failure/cancellation propagation and
9
+ physical-completion tracking. Shared use is not the reason for C06 ownership.
10
+
11
+ There is no universal "one filter per public invocation" policy. Each configured
12
+ stage must retain its position and multiplicity. Registering the same filter
13
+ twice or nesting result decorators remains meaningful application composition.
14
+
15
+ ## Defect
16
+
17
+ In unit 7 and unit 8 a custom call_async delegating with super reached Base's
18
+ default async bridge, which invoked the decorated synchronous call. A second
19
+ decoration then transformed the custom async completion. One configured stage
20
+ therefore ran twice. If the custom implementation additionally mapped the result,
21
+ the first transformation also ran on an intermediate value rather than the
22
+ custom operation's final result.
23
+
24
+ ## Internal delegation
25
+
26
+ Operation.with_result_transform records the exact synchronous wrapper method
27
+ only when that decorator also installs an async completion wrapper. Base's
28
+ call_async obtains a bound synchronous delegate from Operation. That delegate
29
+ skips the leading framework wrappers whose async counterparts already own their
30
+ stages. ToolExecutor receives the callable explicitly and invokes it inline or
31
+ inside the submitted worker, on the original Tool instance.
32
+
33
+ Selection stops at application methods and sync-only decorator stages. Exact
34
+ method matching avoids bypassing a later application replacement, including a
35
+ singleton call override. No Thread/Fiber local flag, per-instance busy flag,
36
+ cloning, value tagging, equality check or filter-identity deduplication is used.
37
+
38
+ ## Application calls remain application calls
39
+
40
+ Only Base's standard async-to-sync bridge is internal delegation. A custom
41
+ implementation that explicitly calls the public call method invokes that
42
+ method's configured transformations. Its async completion can then have its own
43
+ transformation. The framework does not guess whether the application intended
44
+ that explicit call to be raw execution.
45
+
46
+ For example, with a bracket transform:
47
+
48
+ | Composition | Result for x |
49
+ | --- | --- |
50
+ | One stage, custom call_async delegates using super | [x] |
51
+ | Two registrations of the bracket transform | [[x]] |
52
+ | Custom maps super's raw value to custom:x, then one stage | [custom:x] |
53
+ | Custom explicitly calls the decorated public call and prefixes custom: | [custom:[x]] |
54
+
55
+ Applications wanting Base's normal execution as an implementation step should
56
+ use super. Applications can also call their configured filters explicitly; those
57
+ calls are never deduplicated. A custom override inserted between decorators is
58
+ an application boundary, not a wrapper the framework may silently bypass.
59
+
60
+ ## Preserved completion contract
61
+
62
+ Custom completions still use AsyncOperation.map. Original failures retain their
63
+ identity, source cancellation remains cancellation, and physical completion waits
64
+ for both source work and active transformations. Cancelling a mapped result still
65
+ does not implicitly cancel its source. Default cooperative/offloaded dispatch,
66
+ the owning submitter, public keyword arguments, effective names, receiver state,
67
+ and schema/authorization rules remain intact.
68
+
69
+ ## Scope
70
+
71
+ This is a core-only correction. Public signatures and stored schemas are unchanged.
72
+ It does not complete the remaining C01/C02 connections, all C04 composition,
73
+ the source dependency cycles, or the broader acceptance gates.
@@ -21,7 +21,7 @@ because the later W/S sequence has reached its final step.
21
21
 
22
22
  | Owner | Name and location | Reason |
23
23
  |---|---|---|
24
- | Application facade | `Phronomy::Persistence`, `persistence/api` | Users address domain repositories and queries. This class is not the neutral backend contract. |
24
+ | Persistence framework | `Phronomy::Persistence`, `persistence/` | Neutral atomic scopes. Domain stores own queries; composition supplies adapters. The previous shared facade is removed in [r8 unit 3](r8-unit3.md). |
25
25
  | Domain persistence | Agent, MultiAgent and Workflow `persistence` directories | Codecs, durable meanings, result queries and business constraints belong to the feature. |
26
26
  | Resource declarations | Agent persistence, Team/Workflow `storage_contract`, ContentStore | Schemas describe domain metadata; the nested roots keep existing Ruby identities without loading feature runtime just to obtain declarations. |
27
27
  | Common storage | `Phronomy::Storage`, `storage` | Resource/Record/Stream/Blob, conditions and transactions describe backend-neutral mechanisms. |
@@ -332,3 +332,12 @@ and coordinated examples migration. The schema issue is addressed in this candid
332
332
  old empty-schema manifests require completion on the original version before upgrade.
333
333
  Local verification and the exact package trees are recorded in the distribution.
334
334
  User application verification remains outstanding; this is not a published release.
335
+
336
+
337
+ ## Execution abstraction review candidate (2026-09-29)
338
+
339
+ The historical D02 decisions above describe their applied revisions. The current
340
+ unapplied [execution abstraction candidate](execution-abstraction-review.md)
341
+ places child control lifetime behind Execution.start_child and invocation checks
342
+ behind InvocationControls, removing direct OperationBinding ownership from
343
+ Orchestrator. Do not mark this candidate applied until main is verified.
@@ -372,3 +372,19 @@ and coordinated examples migration. The schema issue is addressed in this candid
372
372
  old empty-schema manifests require completion on the original version before upgrade.
373
373
  Local verification and the exact package trees are recorded in the distribution.
374
374
  User application verification remains outstanding; this is not a published release.
375
+
376
+
377
+ ## Execution abstraction review candidate (2026-09-29)
378
+
379
+ The historical D02 decisions above describe their applied revisions. The current
380
+ unapplied [execution abstraction candidate](execution-abstraction-review.md)
381
+ places child control lifetime behind Execution.start_child and invocation checks
382
+ behind InvocationControls, removing direct OperationBinding ownership from
383
+ Orchestrator. Do not mark this candidate applied until main is verified.
384
+
385
+ ## r8 unit 7 scoped update
386
+
387
+ Agent progress/entry operations and top-level execution/recovery connection are
388
+ separated as described in [r8-unit7.md](r8-unit7.md). This supersedes earlier
389
+ AgentInvocationSessionBuilder construction references. Tool child, MultiAgent
390
+ and Workflow connections remain. Overall contract completion is not claimed.
@@ -0,0 +1,54 @@
1
+ # Storage execution units in P4
2
+
3
+ The following 16 submission sites delegate to internal
4
+ `Storage::AsyncClient.submit(pool:)`. Only submission ownership changes: their
5
+ blocks, result callbacks, domain transactions and error/reconciliation policy
6
+ remain in their original owners. Each submitted unit still uses the exact
7
+ pool selected by the owner, with `on_full: :raise` and no new timeout/token.
8
+
9
+ | Owner / source under `lib/phronomy/` | Unit | Result application |
10
+ |---|---|---|
11
+ | `agent/execution/execution_coordinator.rb` | Provider dispatch preparation | ProviderDispatchPreparationReady on EventLoop |
12
+ | same | Tool dispatch preparation | ToolDispatchPreparationReady on EventLoop |
13
+ | same | Uncertain Provider dispatch reconciliation | ProviderDispatchPreparationReconciliationReady |
14
+ | same | Uncertain Tool dispatch reconciliation | ToolDispatchPreparationReconciliationReady |
15
+ | same | Initial invocation preparation | InitialPreparationReady |
16
+ | same | Recovery of initial preparation | InitialPreparationRecoveryReady |
17
+ | same | Approval resume commit | ResumeCommitReady; existing admission handling |
18
+ | same | Terminal outcome commit | TerminalCommitReady; existing save/readback and live-state policy |
19
+ | `agent/execution/exact_execution.rb` | Exact execution read, recovery and materialization | Original observer completion / owner installation |
20
+ | same | Exact execution reconciliation and result materialization | Original observer completion |
21
+ | `agent/recovery/recovery_coordinator/resolution.rb` | Resolution preparation, save/readback and materialization | ResolveReady; validate before applying live state |
22
+ | `workflow/execution/workflow_runner.rb` | Durable snapshot load | Original load-ready command |
23
+ | same | Terminal snapshot save and uncertain-result readback | Original terminal persistence delivery |
24
+ | `multi_agent/durable_subagent_coordinator.rb` | Reserved child load/create/recovery and input materialization | Original exact child execution observer |
25
+ | `multi_agent/team_coordinator.rb` | External cancellation's durable transition | Existing cancellation/readback policy |
26
+ | same | Durable Team Tool operation and reconciliation | Original Tool completion/error policy |
27
+
28
+ The three MultiAgent sites are included because they perform the same kind of
29
+ durable work as Agent and Workflow. They do not introduce a new shared domain
30
+ transaction or move Team rules into Storage.
31
+
32
+ ## Boundaries deliberately retained
33
+
34
+ | Existing boundary | Reason |
35
+ |---|---|
36
+ | Agent approval listener dispatch | Application callback; not a storage operation |
37
+ | ToolExecutor / ToolInvocation authorization pool | Tool execution and authorization; their token/timeout contracts remain distinct |
38
+ | LLM / VectorStore / Embeddings clients | Already own their feature-specific execution boundaries |
39
+ | Tracing and evaluation scorer | Telemetry / scoring work, not storage |
40
+ | MCP cleanup pool | Transport cleanup, not storage |
41
+ | Synchronous Agent load/create, domain repository methods and recovery helpers | Stay synchronous; their existing callers own the offload boundary |
42
+
43
+ Internal submit does not call `backend.transaction`. Public
44
+ `Storage::AsyncClient#transaction_async` opens exactly one outer raw transaction
45
+ on the worker and yields its view. They are separate entry points because a
46
+ durable domain unit may already have transactions, reconciliation reads and
47
+ materialization in a defined order. Adding an outer transaction would change
48
+ that order's commit visibility, connection lifetime and uncertain-result behavior.
49
+
50
+ Runtime tests cover original TaskResult identity, single submission, rollback,
51
+ nested savepoints, scope lifetime, cancellation/timeout and preserved failures.
52
+ Existing Agent/Workflow/Team tests continue to exercise admission, uncertain
53
+ commits and live-state application. Real SQLite verification complements these
54
+ tests; static dependency lines alone do not prove transaction behavior.
@@ -1,5 +1,11 @@
1
1
  # Historical finding: Tool parameter schema is absent from saved definitions
2
2
 
3
+ > Current boundary: r8 unit 6 supersedes the historical Chat/SDK ownership and
4
+ > adapter extension SPI below. Agent uses LLMAdapter values; the backend owns SDK
5
+ > construction/interception; Tool owns canonical schema validation. See
6
+ > `docs/architecture/r8-unit6.md` and `docs/migrations/r8-unit6.md`.
7
+
8
+
3
9
  ## Observed mismatch
4
10
 
5
11
  During Refactor 44 verification, Ruby 3.3.6 with RubyLLM 1.16.0 reproduced the
@@ -164,7 +164,7 @@ redefine the behavior of Application code that directly calls the public
164
164
 
165
165
  ## 10. TokenUsage
166
166
 
167
- `Phronomy::TokenUsage` has four fields:
167
+ `Phronomy::LLMAdapter::TokenUsage` has four fields:
168
168
 
169
169
  ```text
170
170
  input
@@ -10,7 +10,7 @@ Implementation baseline: core `01cd2f57549f6d1e60825254f4520d0f123e651c`
10
10
 
11
11
  FSMSession drives one live state machine on EventLoop. WorkflowRunner assembles
12
12
  Workflow transitions, stream observation and any durable terminal save.
13
- AgentInvocationSessionBuilder uses the same engine for input, LLM and Tool
13
+ InvocationActions and EngineSessionBuilder uses the same engine for input, LLM and Tool
14
14
  progression; ToolInvocationSessionBuilder uses it for authorization, approval
15
15
  and Tool execution. Therefore the session stays in Engine.
16
16
 
@@ -23,7 +23,7 @@ and interpreted its save outcomes. WorkflowTerminalPolicy now owns that rule.
23
23
  |---|---|
24
24
  | FSMSession | Identity/sink, transitions, live context, pending terminal kind/notification flag, event acceptance and final notification/event ordering. |
25
25
  | WorkflowTerminalPolicy | Start the injected save callback; recognize the Workflow result event; map its outcome to a generic terminal decision. |
26
- | FSMProtocol::TerminalDecision | Immutable `action` and `error` value shared by a domain policy and the session. No live session authority. |
26
+ | Phronomy::TerminalDecision | Immutable `action` and `error` value shared by a domain policy and the session. No live session authority. |
27
27
  | WorkflowRunner | Construct a policy for durable execution; retain snapshot capture, one save, F1 readback and caller completion. |
28
28
  | WorkflowExecutionRegistry | Admission, owner tokens, session routing binding and recovery-required ownership. |
29
29
  | EventLoop | Event routing, management events, retirement, source completion and shutdown. |
data/docs/architecture.md CHANGED
@@ -23,6 +23,13 @@ reviewed explicitly rather than resolved by recency.
23
23
 
24
24
  ## Design principles
25
25
 
26
+ The current r8 refinement of Agent parent/Tool child progress and concrete
27
+ execution connections is described in [unit 8](architecture/r8-unit8.md), building
28
+ on [unit 7](architecture/r8-unit7.md). C04 owns Agent progress and approval/recovery;
29
+ C06 owns Tool operations; C13 supplies execution submission/completion. Concrete
30
+ FSM construction stays in Agent runtime_binding. These scoped changes do not
31
+ declare the full contract target or remaining dependency cycles complete.
32
+
26
33
  These are design heuristics for new and revised architecture. They do not
27
34
  override an Accepted ADR, an established public/extension contract, or an
28
35
  explicit compatibility decision.
@@ -105,7 +112,8 @@ synchronous FSM callback exceptions. Recovery owns shared rehydration
105
112
  requirements. Workflow implementation lives under `workflow/execution/`;
106
113
  Agent namespace/event loading lives under `agent/api/`, separately from the shared
107
114
  Agent lifecycle exceptions in `agent/lifecycle_contract/`. LLM values and
108
- call-boundary exceptions live under `llm_contract/`.
115
+ call-boundary exceptions live under `llm_adapter/`, together with the SDK-neutral
116
+ operation contract. See [r8 unit 6](architecture/r8-unit6.md).
109
117
 
110
118
  Agent consumes its private fresh-Persistence factory only when neither an
111
119
  explicit instance nor a configured instance is available. Concrete selection
@@ -175,14 +183,13 @@ confirmed resume. Internal Coordinator type aliases remain, with changed
175
183
  canonical names and an added Command snapshot field. See
176
184
  [ADR-050](decisions/050-approval-resume-snapshot-and-commit-ownership.md).
177
185
 
178
- `Agent::ExecutionOutcomeCommitter` owns ordinary completion, failure, suspension
179
- and child waiting; `Agent::HandoffOutcomeCommitter` adds atomic Source transfer.
180
- The Handoff Coordinator now only selects its worker. Transaction boundaries,
181
- operation-specific readback and Handoff selection precedence remain unchanged.
182
- Coordinator retains quiescence, submission, stale-result validation, live-state
183
- application, admission and Task/listener delivery. Command/view/outcome types are
184
- worker-owned with internal Coordinator aliases and changed canonical Ruby names.
185
- See [ADR-051](decisions/051-execution-outcome-worker-ownership.md).
186
+ `Agent::ExecutionOutcomeCommitter` and `Agent::ExecutionChange` own Agent
187
+ completion, failure, suspension, dispatch preparation and commit proof. A limited
188
+ participant joins its own domain changes to the same scope. MultiAgent owns
189
+ subagent reservations and Handoff routing; it passes extension state and transfer
190
+ receipts, never Agent records or arbitrary update blocks. The EventLoop owner
191
+ continues to apply confirmed results and deliver callbacks. See
192
+ [r8 unit 4](architecture/r8-unit4.md).
186
193
 
187
194
  The remaining execution owner expresses result handling as validation, committed
188
195
  state installation, and continuation or delivery. Private methods keep these
@@ -224,8 +231,10 @@ The Agent entry explicitly preserves Agent lifecycle extension installation.
224
231
  Configuration accessors now live beside Configuration, rather than inside the
225
232
  loader. Configuration constructs fresh components through internally bound
226
233
  factories; composition selects their concrete types. Static source-reference
227
- graphs do not follow these injected calls. LLMAdapter's async bridge still uses
228
- Runtime, and other dependency cycles remain.
234
+ graphs do not follow these injected calls. LLMAdapter's private AsyncClient now
235
+ owns the Runtime dependency; its synchronous Base and RubyLLM implementation
236
+ are independent of Engine. VectorStore/Embeddings migration and other cycles
237
+ remain. See [Backend responsibilities](architecture/backend-groups.md).
229
238
 
230
239
  Agent and Team implement their identity registries in `agent/` and
231
240
  `multi_agent/`. Runtime strongly retains one of each when registered, using only
@@ -254,6 +263,7 @@ generated semantic definition IDs retain their previous values. See
254
263
 
255
264
  | Area | Current document |
256
265
  |---|---|
266
+ | Backend Contracts, Implementations, Async Clients and dependency diagrams | [Backend responsibilities](architecture/backend-groups.md) |
257
267
  | Agent state, identity, ownership, and Context authority | [Agent Context](architecture/agent-context.md) |
258
268
  | Per-LLM-call Context Policy and Manifest construction | [Context Management](architecture/context-management.md) |
259
269
  | Journal-backed Knowledge and retrieval integration | [Knowledge and RAG](architecture/knowledge-and-rag.md) |
@@ -296,3 +306,6 @@ Durable multi-agent coordination is described by [ADR-029](decisions/029-semanti
296
306
  TeamExecution is a purpose-specific CAS authority delegating coordinator/workers
297
307
  to ordinary Agents, with no Team FSMSession or second Workflow engine.
298
308
  Static subagent reservation lives in the existing parent AgentExecution metadata.
309
+
310
+ Current C10/C11 common operation ownership and independent Embeddings/Documents
311
+ placement are specified in [r8 unit 5](architecture/r8-unit5.md).