phronomy 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (557) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +9 -9
  3. data/CHANGELOG.md +92 -0
  4. data/CONTRIBUTING.md +8 -8
  5. data/README.md +13 -3
  6. data/VERIFY.sh +27 -27
  7. data/benchmark/bench_agent_invoke.rb +26 -47
  8. data/benchmark/bench_context_assembler.rb +17 -15
  9. data/benchmark/bench_regression.rb +1 -1
  10. data/benchmark/bench_tool_schema.rb +1 -1
  11. data/docs/architecture/agent-chat-and-state-ownership.md +153 -0
  12. data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
  13. data/docs/architecture/agent-context.md +4 -2
  14. data/docs/architecture/agent-transition-ownership.md +13 -0
  15. data/docs/architecture/backend-groups.md +152 -0
  16. data/docs/architecture/before-llm-input.md +9 -3
  17. data/docs/architecture/context-management.md +31 -1
  18. data/docs/architecture/context-preparation-steps.md +90 -0
  19. data/docs/architecture/entry-action-and-team-wording.md +72 -0
  20. data/docs/architecture/execution-abstraction-review.md +88 -0
  21. data/docs/architecture/execution-boundaries.md +28 -0
  22. data/docs/architecture/execution-metadata-and-values.md +86 -0
  23. data/docs/architecture/generator-verifier-ownership.md +111 -0
  24. data/docs/architecture/multi-agent-handoff.md +11 -4
  25. data/docs/architecture/persistence-refactoring-plan.md +50 -0
  26. data/docs/architecture/persistence.md +45 -4
  27. data/docs/architecture/r8-unit1.md +104 -0
  28. data/docs/architecture/r8-unit10.md +72 -0
  29. data/docs/architecture/r8-unit11.md +71 -0
  30. data/docs/architecture/r8-unit12.md +67 -0
  31. data/docs/architecture/r8-unit13.md +61 -0
  32. data/docs/architecture/r8-unit14.md +72 -0
  33. data/docs/architecture/r8-unit15.md +65 -0
  34. data/docs/architecture/r8-unit16.md +54 -0
  35. data/docs/architecture/r8-unit17.md +73 -0
  36. data/docs/architecture/r8-unit18.md +92 -0
  37. data/docs/architecture/r8-unit19.md +61 -0
  38. data/docs/architecture/r8-unit2.md +55 -0
  39. data/docs/architecture/r8-unit20.md +51 -0
  40. data/docs/architecture/r8-unit21.md +79 -0
  41. data/docs/architecture/r8-unit22.md +74 -0
  42. data/docs/architecture/r8-unit23.md +81 -0
  43. data/docs/architecture/r8-unit3.md +130 -0
  44. data/docs/architecture/r8-unit4.md +79 -0
  45. data/docs/architecture/r8-unit5.md +115 -0
  46. data/docs/architecture/r8-unit6.md +71 -0
  47. data/docs/architecture/r8-unit7.md +70 -0
  48. data/docs/architecture/r8-unit8.md +78 -0
  49. data/docs/architecture/r8-unit9.md +73 -0
  50. data/docs/architecture/refactoring-closure.md +343 -0
  51. data/docs/architecture/remaining-refactoring-plan.md +390 -0
  52. data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
  53. data/docs/architecture/storage-execution-boundaries.md +54 -0
  54. data/docs/architecture/tool-schema-recording-gap.md +56 -0
  55. data/docs/architecture/tracing.md +2 -2
  56. data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
  57. data/docs/architecture.md +222 -0
  58. data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
  59. data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
  60. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
  61. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
  62. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
  63. data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
  64. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +7 -0
  65. data/docs/decisions/031-durable-multi-agent-coordination.md +7 -0
  66. data/docs/decisions/032-storage-backend-composition.md +85 -0
  67. data/docs/decisions/033-domain-persistence-ownership.md +79 -0
  68. data/docs/decisions/034-handoff-runner-coordination-ownership.md +78 -0
  69. data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
  70. data/docs/decisions/036-context-contract-ownership.md +86 -0
  71. data/docs/decisions/037-common-definition-ownership.md +62 -0
  72. data/docs/decisions/038-responsibility-based-source-layout.md +145 -0
  73. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +82 -0
  74. data/docs/decisions/040-configuration-default-composition.md +105 -0
  75. data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
  76. data/docs/decisions/042-feature-owned-execution-state.md +106 -0
  77. data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
  78. data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
  79. data/docs/decisions/045-worker-input-restriction-ownership.md +104 -0
  80. data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
  81. data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
  82. data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
  83. data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
  84. data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
  85. data/docs/decisions/051-execution-outcome-worker-ownership.md +153 -0
  86. data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
  87. data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
  88. data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
  89. data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
  90. data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
  91. data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
  92. data/docs/decisions/058-neutral-storage-primitives.md +83 -0
  93. data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
  94. data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
  95. data/docs/decisions/061-persistence-failure-contracts.md +89 -0
  96. data/docs/decisions/062-content-store-service.md +52 -0
  97. data/docs/decisions/063-execution-contracts-and-services.md +88 -0
  98. data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
  99. data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
  100. data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
  101. data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
  102. data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
  103. data/docs/decisions/README.md +52 -6
  104. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
  105. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
  106. data/docs/execution-boundaries-preview.md +45 -0
  107. data/docs/features.md +16 -5
  108. data/docs/getting-started.md +11 -8
  109. data/docs/migrations/0.15.md +5 -0
  110. data/docs/migrations/0.22.md +2 -2
  111. data/docs/migrations/durable-semantic-coordination-v2.md +8 -0
  112. data/docs/migrations/handoff-runner-multi-agent.md +37 -0
  113. data/docs/migrations/neutral-storage-spi.md +43 -0
  114. data/docs/migrations/parallel-tool-chat-removal.md +49 -0
  115. data/docs/migrations/persistence-failure-contracts.md +67 -0
  116. data/docs/migrations/r8-unit10.md +36 -0
  117. data/docs/migrations/r8-unit11.md +33 -0
  118. data/docs/migrations/r8-unit12.md +31 -0
  119. data/docs/migrations/r8-unit13.md +36 -0
  120. data/docs/migrations/r8-unit14.md +31 -0
  121. data/docs/migrations/r8-unit15.md +31 -0
  122. data/docs/migrations/r8-unit16.md +26 -0
  123. data/docs/migrations/r8-unit17.md +28 -0
  124. data/docs/migrations/r8-unit18.md +29 -0
  125. data/docs/migrations/r8-unit19.md +28 -0
  126. data/docs/migrations/r8-unit20.md +24 -0
  127. data/docs/migrations/r8-unit21.md +28 -0
  128. data/docs/migrations/r8-unit22.md +29 -0
  129. data/docs/migrations/r8-unit23.md +20 -0
  130. data/docs/migrations/r8-unit4.md +67 -0
  131. data/docs/migrations/r8-unit5.md +75 -0
  132. data/docs/migrations/r8-unit6.md +109 -0
  133. data/docs/migrations/r8-unit7.md +31 -0
  134. data/docs/migrations/r8-unit8.md +33 -0
  135. data/docs/migrations/r8-unit9.md +28 -0
  136. data/docs/migrations/shared-state-multi-agent.md +44 -0
  137. data/docs/migrations/storage-async-client.md +103 -0
  138. data/docs/migrations/storage-backend-composition.md +117 -0
  139. data/docs/migrations/storage-transaction-boundaries.md +74 -0
  140. data/docs/migrations/vector-async-clients.md +110 -0
  141. data/docs/persistence-backends.md +190 -215
  142. data/docs/runtime-and-concurrency.md +142 -32
  143. data/lib/phronomy/agent/admission.rb +78 -0
  144. data/lib/phronomy/{agent_already_exists_error.rb → agent/agent_already_exists_error.rb} +2 -0
  145. data/lib/phronomy/{agent_busy_error.rb → agent/agent_busy_error.rb} +2 -0
  146. data/lib/phronomy/{agent_purged_error.rb → agent/agent_purged_error.rb} +2 -0
  147. data/lib/phronomy/agent/api/agent.rb +17 -0
  148. data/lib/phronomy/{execution_rehydration_required_error.rb → agent/api/execution_rehydration_required_error.rb} +2 -0
  149. data/lib/phronomy/agent/async_event_api.rb +38 -33
  150. data/lib/phronomy/agent/base.rb +106 -294
  151. data/lib/phronomy/agent/before_llm_input.rb +64 -0
  152. data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
  153. data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
  154. data/lib/phronomy/agent/context_importer.rb +2 -2
  155. data/lib/phronomy/agent/{context_assembler.rb → context_preparation.rb} +157 -288
  156. data/lib/phronomy/agent/control_request.rb +21 -0
  157. data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
  158. data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +32 -63
  159. data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
  160. data/lib/phronomy/agent/execution/dispatch_preparation.rb +195 -0
  161. data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +43 -23
  162. data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +8 -5
  163. data/lib/phronomy/agent/execution/execution_coordinator.rb +1744 -0
  164. data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
  165. data/lib/phronomy/agent/execution/execution_metadata.rb +54 -0
  166. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +288 -0
  167. data/lib/phronomy/agent/execution/execution_registry.rb +463 -0
  168. data/lib/phronomy/agent/execution/execution_session_runner.rb +113 -0
  169. data/lib/phronomy/agent/execution/initial_preparation.rb +323 -0
  170. data/lib/phronomy/agent/execution/invocation_actions.rb +368 -0
  171. data/lib/phronomy/agent/execution/invocation_transitions.rb +124 -0
  172. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
  173. data/lib/phronomy/agent/execution_change.rb +161 -0
  174. data/lib/phronomy/agent/execution_environment.rb +36 -0
  175. data/lib/phronomy/agent/execution_extension_state.rb +21 -0
  176. data/lib/phronomy/agent/execution_observation.rb +35 -0
  177. data/lib/phronomy/agent/filterable.rb +182 -0
  178. data/lib/phronomy/agent/{handoff_context.rb → handoff/transfer_context.rb} +6 -6
  179. data/lib/phronomy/agent/{handoff_projection.rb → handoff/transfer_projection.rb} +14 -33
  180. data/lib/phronomy/agent/handoff_error.rb +7 -0
  181. data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
  182. data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
  183. data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
  184. data/lib/phronomy/agent/knowledge_item.rb +13 -0
  185. data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
  186. data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
  187. data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -15
  188. data/lib/phronomy/agent/persistence/agent_repository.rb +69 -0
  189. data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
  190. data/lib/phronomy/agent/persistence/codec.rb +338 -0
  191. data/lib/phronomy/agent/persistence/execution_repository.rb +124 -0
  192. data/lib/phronomy/agent/persistence/journal_repository.rb +63 -0
  193. data/lib/phronomy/agent/persistence/records.rb +33 -0
  194. data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
  195. data/lib/phronomy/agent/persistence/storage_schema.rb +29 -0
  196. data/lib/phronomy/agent/persistence/watermark.rb +29 -0
  197. data/lib/phronomy/agent/recovery/invocation_restorer.rb +124 -0
  198. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +28 -51
  199. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +50 -55
  200. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +38 -43
  201. data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +26 -23
  202. data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
  203. data/lib/phronomy/agent/recovery/recovery_support.rb +224 -0
  204. data/lib/phronomy/agent/reserved_execution.rb +16 -0
  205. data/lib/phronomy/agent/retention.rb +17 -0
  206. data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
  207. data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
  208. data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
  209. data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
  210. data/lib/phronomy/agent/{ruby_llm_materializer.rb → runtime_input.rb} +19 -39
  211. data/lib/phronomy/agent/saved_context_reader.rb +55 -0
  212. data/lib/phronomy/agent/settings.rb +47 -0
  213. data/lib/phronomy/agent/state_writer.rb +166 -0
  214. data/lib/phronomy/agent/store.rb +253 -0
  215. data/lib/phronomy/{stream_callback_error.rb → agent/stream_callback_error.rb} +2 -0
  216. data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
  217. data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
  218. data/lib/phronomy/agent/tool_execution/tool_binding.rb +30 -0
  219. data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +114 -248
  220. data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
  221. data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
  222. data/lib/phronomy/common/configuration_error.rb +7 -0
  223. data/lib/phronomy/common/error.rb +5 -0
  224. data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
  225. data/lib/phronomy/common/values/serializable.rb +32 -0
  226. data/lib/phronomy/configuration/runtime_settings.rb +49 -0
  227. data/lib/phronomy/content_store/storage_schema.rb +12 -0
  228. data/lib/phronomy/content_store/stored_contents.rb +44 -0
  229. data/lib/phronomy/context/assembly.rb +202 -0
  230. data/lib/phronomy/{context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +5 -1
  231. data/lib/phronomy/context/candidate.rb +51 -0
  232. data/lib/phronomy/context/constraint.rb +47 -0
  233. data/lib/phronomy/{agent → context}/context_plan.rb +2 -2
  234. data/lib/phronomy/{agent → context}/context_plan_validator.rb +3 -3
  235. data/lib/phronomy/{agent → context}/context_policy.rb +1 -1
  236. data/lib/phronomy/{agent → context}/context_policy_input.rb +7 -7
  237. data/lib/phronomy/{agent → context}/context_policy_input_builder.rb +1 -1
  238. data/lib/phronomy/context/default_policy.rb +140 -0
  239. data/lib/phronomy/context/final_budget_validator.rb +33 -0
  240. data/lib/phronomy/{agent → context}/llm_input_build_context.rb +2 -2
  241. data/lib/phronomy/{agent → context}/llm_input_manifest.rb +21 -21
  242. data/lib/phronomy/{agent → context}/llm_input_patch.rb +3 -3
  243. data/lib/phronomy/context/manifest_error.rb +10 -0
  244. data/lib/phronomy/context/prompt_template.rb +98 -0
  245. data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
  246. data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
  247. data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
  248. data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
  249. data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
  250. data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
  251. data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
  252. data/lib/phronomy/embeddings/async/async_client.rb +44 -0
  253. data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +48 -0
  254. data/lib/phronomy/embeddings/base.rb +43 -0
  255. data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
  256. data/lib/phronomy/embeddings/transport_error.rb +11 -0
  257. data/lib/phronomy/engine/concurrency/offload_pool.rb +39 -20
  258. data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
  259. data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +1 -1
  260. data/lib/phronomy/engine/event_loop.rb +164 -630
  261. data/lib/phronomy/engine/execution_binding.rb +23 -0
  262. data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
  263. data/lib/phronomy/engine/fsm_protocol.rb +9 -0
  264. data/lib/phronomy/engine/fsm_session.rb +37 -30
  265. data/lib/phronomy/engine/metrics.rb +28 -0
  266. data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
  267. data/lib/phronomy/engine/runtime.rb +104 -95
  268. data/lib/phronomy/engine/terminal_decision.rb +7 -0
  269. data/lib/phronomy/execution/async_operation.rb +41 -0
  270. data/lib/phronomy/execution/backpressure_error.rb +7 -0
  271. data/lib/phronomy/{blocking.rb → execution/blocking.rb} +2 -2
  272. data/lib/phronomy/execution/cancellation_error.rb +7 -0
  273. data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +5 -1
  274. data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
  275. data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
  276. data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
  277. data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
  278. data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
  279. data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
  280. data/lib/phronomy/execution/concurrency/worker_input_restricted.rb +14 -0
  281. data/lib/phronomy/execution/event_loop_reentrancy_error.rb +8 -0
  282. data/lib/phronomy/{execution.rb → execution/execution.rb} +57 -30
  283. data/lib/phronomy/{execution_cancellation_error.rb → execution/execution_cancellation_error.rb} +2 -0
  284. data/lib/phronomy/execution/execution_receiver.rb +78 -0
  285. data/lib/phronomy/execution/execution_scope_state.rb +35 -0
  286. data/lib/phronomy/{execution_timeout_error.rb → execution/execution_timeout_error.rb} +2 -0
  287. data/lib/phronomy/{invalid_async_entry_action_error.rb → execution/invalid_async_entry_action_error.rb} +2 -0
  288. data/lib/phronomy/{invalid_async_transition_action_error.rb → execution/invalid_async_transition_action_error.rb} +2 -0
  289. data/lib/phronomy/{invalid_async_workflow_action_error.rb → execution/invalid_async_workflow_action_error.rb} +2 -0
  290. data/lib/phronomy/{invocation_context.rb → execution/invocation_context.rb} +0 -15
  291. data/lib/phronomy/execution/invocation_controls.rb +73 -0
  292. data/lib/phronomy/execution/pool_shutdown_error.rb +7 -0
  293. data/lib/phronomy/execution/recursion_limit_error.rb +7 -0
  294. data/lib/phronomy/execution/runnable.rb +24 -0
  295. data/lib/phronomy/execution/runtime_shutdown_error.rb +7 -0
  296. data/lib/phronomy/execution/runtime_shutdown_reentrancy_error.rb +7 -0
  297. data/lib/phronomy/execution/scheduler_reentrancy_error.rb +9 -0
  298. data/lib/phronomy/{engine → execution}/task_result.rb +7 -3
  299. data/lib/phronomy/execution/timeout_error.rb +7 -0
  300. data/lib/phronomy/execution/wait_policy.rb +24 -0
  301. data/lib/phronomy/filter/filter_block_error.rb +14 -0
  302. data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
  303. data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
  304. data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
  305. data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
  306. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
  307. data/lib/phronomy/generation/generator_verifier.rb +118 -0
  308. data/lib/phronomy/generation/low_confidence_error.rb +14 -0
  309. data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
  310. data/lib/phronomy/llm_adapter/authentication_error.rb +9 -0
  311. data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
  312. data/lib/phronomy/llm_adapter/base.rb +49 -68
  313. data/lib/phronomy/llm_adapter/context_length_error.rb +9 -0
  314. data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
  315. data/lib/phronomy/llm_adapter/message.rb +62 -0
  316. data/lib/phronomy/llm_adapter/rate_limit_error.rb +9 -0
  317. data/lib/phronomy/llm_adapter/request.rb +79 -0
  318. data/lib/phronomy/llm_adapter/response.rb +36 -0
  319. data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
  320. data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
  321. data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
  322. data/lib/phronomy/llm_adapter.rb +3 -16
  323. data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
  324. data/lib/phronomy/multi_agent/admission_registry.rb +15 -2
  325. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
  326. data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
  327. data/lib/phronomy/{agent → multi_agent}/handoff.rb +2 -2
  328. data/lib/phronomy/{agent → multi_agent}/handoff_capability_factory.rb +21 -2
  329. data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
  330. data/lib/phronomy/{agent → multi_agent}/handoff_policy.rb +1 -1
  331. data/lib/phronomy/multi_agent/handoff_runner.rb +156 -0
  332. data/lib/phronomy/{agent → multi_agent}/handoff_state.rb +2 -2
  333. data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
  334. data/lib/phronomy/multi_agent/persistence/codec.rb +75 -0
  335. data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
  336. data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
  337. data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
  338. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +124 -0
  339. data/lib/phronomy/multi_agent/persistence/team_repository.rb +69 -0
  340. data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
  341. data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
  342. data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
  343. data/lib/phronomy/multi_agent/store.rb +156 -0
  344. data/lib/phronomy/multi_agent/team_coordinator.rb +87 -75
  345. data/lib/phronomy/multi_agent/team_execution.rb +1 -1
  346. data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +5 -5
  347. data/lib/phronomy/multi_agent/team_root.rb +1 -1
  348. data/lib/phronomy/output_parser/parse_error.rb +7 -0
  349. data/lib/phronomy/persistence/content_repository.rb +26 -0
  350. data/lib/phronomy/persistence/errors.rb +16 -0
  351. data/lib/phronomy/persistence/migration/initial_format_migration.rb +21 -21
  352. data/lib/phronomy/persistence/persistence.rb +23 -0
  353. data/lib/phronomy/persistence/save_outcome.rb +24 -0
  354. data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
  355. data/lib/phronomy/persistence/storage_boundary.rb +32 -0
  356. data/lib/phronomy/persistence/transaction.rb +86 -0
  357. data/lib/phronomy/persistence_composition/storage_schema.rb +29 -0
  358. data/lib/phronomy/persistence_composition/stores.rb +34 -0
  359. data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
  360. data/lib/phronomy/runtime_composition/agent_defaults.rb +11 -0
  361. data/lib/phronomy/runtime_composition/configuration.rb +146 -0
  362. data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
  363. data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
  364. data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
  365. data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
  366. data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
  367. data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
  368. data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
  369. data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
  370. data/lib/phronomy/storage/async/async_client.rb +60 -0
  371. data/lib/phronomy/storage/backend.rb +107 -0
  372. data/lib/phronomy/storage/backends/in_memory.rb +157 -0
  373. data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
  374. data/lib/phronomy/storage/blobs.rb +31 -0
  375. data/lib/phronomy/storage/condition.rb +25 -0
  376. data/lib/phronomy/storage/condition_failed_error.rb +16 -0
  377. data/lib/phronomy/storage/conflict_error.rb +9 -0
  378. data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
  379. data/lib/phronomy/storage/entry.rb +33 -0
  380. data/lib/phronomy/storage/guard_ref.rb +13 -0
  381. data/lib/phronomy/storage/not_found_error.rb +9 -0
  382. data/lib/phronomy/storage/record_codec.rb +177 -0
  383. data/lib/phronomy/storage/records.rb +61 -0
  384. data/lib/phronomy/storage/resource.rb +126 -0
  385. data/lib/phronomy/storage/scope.rb +25 -0
  386. data/lib/phronomy/storage/serialization_error.rb +9 -0
  387. data/lib/phronomy/storage/streams.rb +44 -0
  388. data/lib/phronomy/storage/transaction_error.rb +10 -0
  389. data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
  390. data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
  391. data/lib/phronomy/storage/validation.rb +53 -0
  392. data/lib/phronomy/storage/view.rb +131 -0
  393. data/lib/phronomy/testing/eval/metrics.rb +1 -1
  394. data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
  395. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
  396. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
  397. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +54 -48
  398. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +1 -1
  399. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +1 -1
  400. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
  401. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +52 -46
  402. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
  403. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +124 -0
  404. data/lib/phronomy/testing/persistence_contract.rb +4 -0
  405. data/lib/phronomy/tool/authorization.rb +77 -0
  406. data/lib/phronomy/tool/base.rb +549 -9
  407. data/lib/phronomy/tool/call_request.rb +40 -0
  408. data/lib/phronomy/{agent/tool_definition_set.rb → tool/definition_set.rb} +16 -12
  409. data/lib/phronomy/tool/operation.rb +88 -0
  410. data/lib/phronomy/tool/schema.rb +214 -0
  411. data/lib/phronomy/tool/settings.rb +31 -0
  412. data/lib/phronomy/tool/tool_error.rb +7 -0
  413. data/lib/phronomy/{agent → tool}/tool_executor.rb +10 -7
  414. data/lib/phronomy/tools/agent.rb +22 -90
  415. data/lib/phronomy/tools/mcp.rb +21 -14
  416. data/lib/phronomy/tools/vector_search.rb +4 -4
  417. data/lib/phronomy/tracing/automatic.rb +11 -6
  418. data/lib/phronomy/tracing/base.rb +1 -1
  419. data/lib/phronomy/tracing/observation.rb +37 -0
  420. data/lib/phronomy/tracing/settings.rb +36 -0
  421. data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
  422. data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
  423. data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
  424. data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
  425. data/lib/phronomy/vector_store/base.rb +118 -49
  426. data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
  427. data/lib/phronomy/vector_store.rb +2 -17
  428. data/lib/phronomy/version.rb +1 -1
  429. data/lib/phronomy/workflow/completion.rb +11 -0
  430. data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +10 -8
  431. data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
  432. data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +5 -1
  433. data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
  434. data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +27 -0
  435. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +186 -0
  436. data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +145 -115
  437. data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
  438. data/lib/phronomy/workflow/persistence/codec.rb +153 -0
  439. data/lib/phronomy/workflow/persistence/state_repository.rb +63 -0
  440. data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
  441. data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +38 -0
  442. data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +156 -0
  443. data/lib/phronomy/workflow/runtime_binding/workflow_terminal_policy.rb +40 -0
  444. data/lib/phronomy.rb +97 -98
  445. data/scripts/api_snapshot.rb +36 -16
  446. data/scripts/storage_spi_snapshot.rb +36 -0
  447. data/sig/_private/phronomy/agent/settings.rbs +19 -0
  448. data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
  449. data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
  450. data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
  451. data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
  452. data/sig/_private/phronomy/tool/settings.rbs +13 -0
  453. data/sig/_private/phronomy/tracing/settings.rbs +15 -0
  454. data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
  455. data/sig/phronomy/agent/admission.rbs +19 -0
  456. data/sig/phronomy/agent/execution_contract.rbs +132 -0
  457. data/sig/phronomy/agent/execution_environment.rbs +20 -0
  458. data/sig/phronomy/agent/store.rbs +73 -0
  459. data/sig/phronomy/agent.rbs +14 -139
  460. data/sig/phronomy/common.rbs +7 -0
  461. data/sig/phronomy/content_store/contracts.rbs +13 -0
  462. data/sig/phronomy/context.rbs +152 -0
  463. data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
  464. data/sig/phronomy/embeddings/base.rbs +17 -0
  465. data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
  466. data/sig/phronomy/engine/control_bindings.rbs +11 -0
  467. data/sig/phronomy/engine/control_protocols.rbs +23 -0
  468. data/sig/phronomy/engine/execution_binding.rbs +6 -0
  469. data/sig/phronomy/engine/execution_receiver.rbs +15 -0
  470. data/sig/phronomy/engine/observability.rbs +13 -0
  471. data/sig/phronomy/execution/async_operation.rbs +7 -0
  472. data/sig/phronomy/execution/blocking.rbs +5 -0
  473. data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
  474. data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
  475. data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
  476. data/sig/phronomy/execution/control_protocols.rbs +18 -0
  477. data/sig/phronomy/execution/errors.rbs +7 -0
  478. data/sig/phronomy/execution/execution.rbs +41 -0
  479. data/sig/phronomy/execution/execution_receiver.rbs +40 -0
  480. data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
  481. data/sig/phronomy/execution/invocation_context.rbs +18 -0
  482. data/sig/phronomy/execution/invocation_controls.rbs +13 -0
  483. data/sig/phronomy/execution/task_result.rbs +29 -0
  484. data/sig/phronomy/extensions.rbs +0 -21
  485. data/sig/phronomy/handoff.rbs +12 -4
  486. data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
  487. data/sig/phronomy/llm_adapter/base.rbs +14 -0
  488. data/sig/phronomy/llm_adapter/usage.rbs +14 -0
  489. data/sig/phronomy/llm_adapter/values.rbs +43 -0
  490. data/sig/phronomy/llm_context_window.rbs +10 -0
  491. data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
  492. data/sig/phronomy/multi_agent/store.rbs +54 -0
  493. data/sig/phronomy/multi_agent.rbs +24 -3
  494. data/sig/phronomy/persistence/errors.rbs +18 -0
  495. data/sig/phronomy/persistence/migration.rbs +13 -0
  496. data/sig/phronomy/persistence/transaction.rbs +19 -0
  497. data/sig/phronomy/persistence.rbs +3 -185
  498. data/sig/phronomy/persistence_composition.rbs +19 -0
  499. data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
  500. data/sig/phronomy/storage/async/async_client.rbs +8 -0
  501. data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
  502. data/sig/phronomy/storage/contracts.rbs +160 -0
  503. data/sig/phronomy/tool.rbs +58 -5
  504. data/sig/phronomy/tracing/observation.rbs +7 -0
  505. data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
  506. data/sig/phronomy/vector_store/base.rbs +23 -0
  507. data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +14 -0
  508. data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
  509. data/sig/phronomy/workflow/store.rbs +8 -0
  510. data/sig/phronomy/workflow.rbs +1 -1
  511. data/sig/phronomy.rbs +0 -49
  512. metadata +462 -130
  513. data/lib/phronomy/agent/agent_invocation_session_builder.rb +0 -584
  514. data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
  515. data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
  516. data/lib/phronomy/agent/concerns/filterable.rb +0 -184
  517. data/lib/phronomy/agent/context/capability/base.rb +0 -507
  518. data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
  519. data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
  520. data/lib/phronomy/agent/context_policies/default.rb +0 -142
  521. data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
  522. data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
  523. data/lib/phronomy/agent/handoff_request.rb +0 -45
  524. data/lib/phronomy/agent/handoff_runner.rb +0 -178
  525. data/lib/phronomy/agent/phase_machine_builder.rb +0 -152
  526. data/lib/phronomy/agent/provider_call_outcome.rb +0 -106
  527. data/lib/phronomy/agent/recovery_support.rb +0 -504
  528. data/lib/phronomy/agent/selection/candidate.rb +0 -53
  529. data/lib/phronomy/agent/selection/constraint.rb +0 -49
  530. data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
  531. data/lib/phronomy/agent/tool_call_intercepted.rb +0 -29
  532. data/lib/phronomy/agent/tool_invocation_session_builder.rb +0 -276
  533. data/lib/phronomy/configuration.rb +0 -59
  534. data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
  535. data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
  536. data/lib/phronomy/generator_verifier.rb +0 -369
  537. data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
  538. data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
  539. data/lib/phronomy/metrics.rb +0 -26
  540. data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
  541. data/lib/phronomy/persistence/durable_codec.rb +0 -706
  542. data/lib/phronomy/persistence/in_memory.rb +0 -690
  543. data/lib/phronomy/persistence/repository_facades.rb +0 -535
  544. data/lib/phronomy/persistence.rb +0 -276
  545. data/lib/phronomy/recovery.rb +0 -186
  546. data/lib/phronomy/ruby_llm_patches.rb +0 -24
  547. data/lib/phronomy/runnable.rb +0 -54
  548. data/lib/phronomy/token_usage.rb +0 -85
  549. data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
  550. data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
  551. data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
  552. data/lib/phronomy/workflow_recovery.rb +0 -123
  553. data/sig/phronomy/llm_adapter.rbs +0 -11
  554. data/sig/phronomy/runtime.rbs +0 -76
  555. /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
  556. /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
  557. /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
@@ -0,0 +1,33 @@
1
+ # Migrating to r8 unit 8
2
+
3
+ Apply after core a601a0654ace42640f0251b129359ca1f326e3ad (unit 7).
4
+ This is a core-only change. The unit 6 examples at
5
+ ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
6
+
7
+ Public Agent invocation/stream/approval/cancellation/recovery signatures and
8
+ Tool#call_async(args, cancellation_token:, config:) are unchanged. Tool::Operation
9
+ adds an explicit C06 operation entry and result transformation API; application
10
+ Tools do not need to adopt it. The supplied submitter applies to the default
11
+ offloaded operation only. Custom async implementations retain their existing
12
+ execution mechanism and configuration.
13
+
14
+ | Internal use | Replacement |
15
+ | --- | --- |
16
+ | Agent::ToolInvocationSessionBuilder.build / build_for_resume | The owning ExecutionEnvironment.build_tool_session, with resume_event/resume_phase when needed |
17
+ | ToolInvocationSessionBuilder transition constants | Agent::ToolInvocationTransitions |
18
+ | ToolInvocationSessionBuilder entry operations | Agent::ToolInvocationActions |
19
+ | ToolInvocation.start_authorization/runtime: and start_execution/runtime: | Pass environment: explicitly; never reconstruct it from a new global Runtime |
20
+ | Tool::ToolExecutor.call_async(runtime:) | Tool::Operation.call_async(submitter:) for contract consumers; default executor takes submitter: internally |
21
+ | Agent ToolBinding's custom-async detection and mapping mechanism | Tool::Operation.with_result_transform; Agent retains filter configuration |
22
+
23
+ Removed internal names have no aliases. Deploy all internal call sites together.
24
+ Do not persist execution environments, submitters, FSM sessions or parent sinks.
25
+ Durable IDs, record schemas, revision checks and saved approval evidence are
26
+ unchanged. The change does not certify new in-flight cross-version compatibility.
27
+ Use the existing stop/drain procedure before replacing running processes.
28
+
29
+ The application ZIP contains strict-base --check/--apply/--verify commands,
30
+ complete replacement files and deletions, expected-tree verification, a review
31
+ patch, validation evidence and rollback instructions. Run --verify before and
32
+ after commit. Verify examples with PHRONOMY_PATH pointing at the candidate and
33
+ unset a stale BUNDLE_GEMFILE before entering each Bundler context.
@@ -0,0 +1,28 @@
1
+ # R8 unit 9 migration
2
+
3
+ Apply to core unit 8, commit e9f6cc16da19be82a0b7777486926ba46d070def.
4
+ Examples source remains at unit 6, ed455c52018338f7c5a4c2948ae0d7db131aa090.
5
+
6
+ No public Tool or Agent signature, stored schema, migration CLI or example source
7
+ change is required. Existing configured filter order and repeated registrations
8
+ are preserved. The correction removes only the extra transformation caused by
9
+ Base's standard async-to-sync delegation under a custom async result decorator.
10
+
11
+ A custom call_async using super now passes its raw delegated result through its
12
+ own processing before the async decorator applies the configured transform.
13
+ Code accidentally relying on the duplicate/intermediate transformation should
14
+ express the required stages explicitly in application filter configuration.
15
+
16
+ A custom call_async explicitly calling public call retains that call's filters;
17
+ the enclosing async result decorator also retains its stage. Do not substitute
18
+ call for super when the intent is to delegate to Base's normal async execution.
19
+ The framework does not suppress application-authored calls or infer their intent.
20
+
21
+ Private changes: Base uses Tool::Operation.synchronous_delegate; ToolExecutor
22
+ accepts a bound synchronous_call keyword. Applications should not use these
23
+ private bridge helpers. Custom async implementations retain their existing
24
+ execution mechanism and keyword protocol.
25
+
26
+ Use the normal process stop/drain and restart procedure. This unit does not add
27
+ cross-version in-flight compatibility or rollback of external Tool side effects.
28
+ See docs/architecture/r8-unit9.md for operation-boundary examples.
@@ -0,0 +1,44 @@
1
+ # SharedState moves to MultiAgent
2
+
3
+ This change applies to the architecture refactoring branch after core commit
4
+ `aa9c3d53090bda4deb01b8cab16a43539b6b1deb`. Use the matching core and examples
5
+ checkouts; the unchanged gem version number alone does not identify this API.
6
+
7
+ | Previous Experimental API | API after this change |
8
+ |---|---|
9
+ | `Phronomy::Agent::SharedState` | `Phronomy::MultiAgent::SharedState` |
10
+ | `Phronomy::Agent::SharedState::KnowledgeStore` | `Phronomy::MultiAgent::SharedState::KnowledgeStore` |
11
+
12
+ The previous name is removed without an alias. Update superclass declarations
13
+ and explicit constant references. For example:
14
+
15
+ ```ruby
16
+ require "phronomy"
17
+
18
+ class ResearchTeam < Phronomy::MultiAgent::SharedState
19
+ member Researcher
20
+ max_cycles 3
21
+ end
22
+ ```
23
+
24
+ Use the public application entry point `require "phronomy"`. The old internal
25
+ file `phronomy/agent/shared_state.rb` is removed; arbitrary implementation-file
26
+ requires are not a supported partial-loading API.
27
+
28
+ The DSL, `invoke(input, config: {})` signature, sequential order, shared findings,
29
+ termination rules and `{output:, cycles:, terminated_by:}` result remain the same.
30
+ `config:` remains accepted but is not forwarded to member invocations. Timeout
31
+ is checked between complete cycles and does not cancel an active Agent.
32
+
33
+ Set `PHRONOMY_PATH` to the matching local core checkout before running
34
+ `bundle install` or the examples verification. Example `22_shared_state` now
35
+ uses the new superclass, and the examples API preflight rejects mismatched core.
36
+
37
+ No saved-record or SQL schema migration is required. Do not rewrite the existing
38
+ `Phronomy::Agent::SharedState::Instrumented/` generated definition ID: it is
39
+ deliberately preserved together with instrumentation version 1. It is not an
40
+ alias for the removed Ruby constant. The in-memory KnowledgeStore still lasts
41
+ for one invocation only.
42
+
43
+ See [ADR-053](../decisions/053-shared-state-coordination-ownership.md) for the
44
+ ownership and compatibility decision.
@@ -0,0 +1,103 @@
1
+ # Storage asynchronous execution and ContentStore ownership
2
+
3
+ P4 adds the public Beta `Phronomy::Storage::AsyncClient`. Synchronous storage
4
+ backends and `Persistence#transaction` keep their existing interfaces. Backend
5
+ authors implement no scheduler or async methods.
6
+
7
+ ## Public transaction API
8
+
9
+ Construct `Storage::AsyncClient.new(backend: raw_backend, pool: nil)` around a
10
+ Storage SPI 2 backend. For an existing Persistence facade, use
11
+ `persistence.backend`. The transaction block receives a **raw Storage::View**,
12
+ not the domain repositories yielded by `Persistence#transaction`.
13
+
14
+ `transaction_async(cancellation_token: nil, timeout: nil) { |view| ... }`
15
+ returns the pool's original TaskResult. The complete transaction runs on one
16
+ worker, using the backend's normal connection and scope. Do not split a
17
+ transaction across workers or wait for another TaskResult inside its block.
18
+ Explicit synchronous `backend.transaction` calls within the block retain nested
19
+ savepoint behavior.
20
+
21
+ ### Complete offline example
22
+
23
+ This requires a checkout containing P4; the previously released 0.27.0 gem does
24
+ not contain the new client. It uses only the public raw storage contract.
25
+
26
+ ```ruby runnable
27
+ require "phronomy"
28
+ require "json"
29
+
30
+ resource = Phronomy::Storage::Resource.new(id: "example.notes", kind: :records)
31
+ backend = Phronomy::Storage::Backends::InMemory.new(resources: [resource])
32
+ client = Phronomy::Storage::AsyncClient.new(backend: backend)
33
+
34
+ begin
35
+ record = Phronomy::Storage::DurableRecord.new(
36
+ record_type: "example.note", format_version: "0.1", payload: {"text" => "saved"}
37
+ )
38
+ task = client.transaction_async do |view|
39
+ rows = view.records(resource)
40
+ rows.insert(key: "note-1", revision: 1, attributes: {}, record: record)
41
+ rows.fetch("note-1").record.payload
42
+ end
43
+ puts JSON.generate(task.wait_result)
44
+ ensure
45
+ Phronomy.reset_runtime!
46
+ end
47
+ ```
48
+
49
+ The output is `{"text":"saved"}`. Return a value from the transaction. A bound
50
+ view or resource handle becomes invalid after the block finishes, even if it
51
+ was returned through TaskResult. Scope also rejects access from another thread.
52
+ Exceptions and invalid non-local block exits roll back through the existing
53
+ backend rules; no new transaction implementation is introduced.
54
+
55
+ ## Admission, cancellation and ownership
56
+
57
+ Construction starts no Runtime. Each call resolves the current default pool,
58
+ unless an explicit caller-owned `pool:` was supplied. Runtime reset does not
59
+ transfer ownership of an injected pool.
60
+
61
+ Admission uses `on_full: :raise`: a full or stopped pool raises immediately.
62
+ Queue wait counts toward `timeout`. Cancellation/timeout before worker pickup
63
+ skips the transaction. After work starts, TaskResult may settle while the
64
+ physical transaction continues and commits. A timeout or cancellation is **not
65
+ a rollback guarantee**. The client does not kill a thread, add retries, or claim
66
+ that an uncertain commit succeeded or failed. Applications needing a durable
67
+ outcome must reconcile through their domain's identities and stored state.
68
+
69
+ ## Existing Agent, Workflow and coordination operations
70
+
71
+ Internal `Storage::AsyncClient.submit(pool:)` accepts an existing synchronous
72
+ storage unit. This is private framework API, not an application extension API.
73
+ It submits exactly once and adds no transaction, token, or timeout. This lets
74
+ domain operations preserve their own transaction and reconciliation boundaries.
75
+ See the [operation inventory](../architecture/storage-execution-boundaries.md).
76
+
77
+ In particular, a Workflow runner may have only an injected repository rather
78
+ than access to its raw backend. Internal submit therefore accepts a callable
79
+ and the owner's pool; it does not require a dummy backend or a Persistence
80
+ facade. Public transaction_async requires a real SPI 2 backend.
81
+
82
+ Durable commit/readback policy, admission release, callback delivery and the
83
+ application of results to live state remain with Agent/Workflow/MultiAgent.
84
+ No cancellation condition is added to existing terminal saves. Tool execution,
85
+ authorization, tracing and application approval listeners retain their own
86
+ execution boundaries.
87
+
88
+ ## ContentStore path and diagram
89
+
90
+ P4 originally moved `ContentStore::StoredContents` into
91
+ `content_store/backends/stored_contents.rb`. [ADR-062](../decisions/062-content-store-service.md)
92
+ supersedes that split: the implementation now lives at
93
+ `content_store/stored_contents.rb`, beside its shared API and owned schema.
94
+ The obsolete backend directory and collapse entry are deleted without a shim.
95
+ Its constant, synchronous operations, digest rules and exceptions are unchanged.
96
+ Use normal `require "phronomy"`; internal file paths are not a public load API.
97
+ Zeitwerk still collapses `storage/async/`. `Storage::Backends` remains a namespace.
98
+ ContentStore receives no artificial async API.
99
+
100
+ M10 is G57 Content Service in B3, outside Backend Contracts/Implementations;
101
+ M73 is retired. M69 Storage AsyncClient stays in B4. Text panels are transparent.
102
+ Arrows targeting M33/M41/M44 are hidden by display settings; all measured
103
+ dependencies, source evidence and matrix cells remain available.
@@ -0,0 +1,117 @@
1
+ # Storage Backend composition migration
2
+
3
+ Historical migration step. Its old raw SPI surface is superseded by the
4
+ [neutral Storage SPI 2 migration](neutral-storage-spi.md); use that guide for the
5
+ current backend contract.
6
+
7
+
8
+ This change targets the `refactor/architecture` branch after `1b481f6`, with
9
+ shared value operations already owned by `Values::Immutable`.
10
+ It replaces the Beta Backend SPI; the gem version and persisted record formats
11
+ are not changed by this branch-only refactoring package.
12
+
13
+ ## Application construction
14
+
15
+ An isolated in-memory domain is now constructed with:
16
+
17
+ ```ruby
18
+ require "phronomy"
19
+
20
+ persistence = Phronomy::Persistence.in_memory
21
+ Phronomy.configure { |config| config.persistence = persistence }
22
+ ```
23
+
24
+ An explicitly selected raw backend is composed once:
25
+
26
+ ```ruby
27
+ require "phronomy"
28
+
29
+ backend = Phronomy::Storage::Backends::InMemory.new
30
+ persistence = Phronomy::Persistence.new(backend: backend)
31
+ Phronomy.configure { |config| config.persistence = persistence }
32
+ ```
33
+
34
+ Use the same `persistence` instance wherever one storage/ownership domain is
35
+ required. Constructing several facades over one physical backend does not create
36
+ independent data, and their object identities are distinct for callers that use
37
+ Persistence identity to determine a domain. `persistence.backend` exposes the
38
+ selected raw backend for backend-specific administration such as accessing its
39
+ connection pool. Ordinary domain reads and writes still use `persistence`.
40
+
41
+ ## Replaced API
42
+
43
+ | Previous API | Replacement |
44
+ |---|---|
45
+ | `Persistence::InMemory.new` | `Persistence.in_memory` |
46
+ | Backend subclass of `Persistence` | Backend subclass of `Storage::Backend`, or the same raw protocol |
47
+ | `Persistence.new` with eight raw repository keyword arguments | `Persistence.new(backend: raw_backend)` |
48
+ | Backend `super` with eight repositories | The same arguments passed to `Storage::Backend#initialize` |
49
+ | `Persistence#build_transaction_view` | A raw `Storage::Repositories` view yielded by the backend |
50
+ | `Persistence::DurableRecord` | `Storage::DurableRecord` |
51
+ | `Persistence::ConflictError` / `NotFoundError` / `SerializationError` / `UnsupportedBackendError` | The same names under `Storage` |
52
+ | `Persistence::REQUIRED_CAPABILITIES` | `Storage::Backend::REQUIRED_CAPABILITIES` |
53
+
54
+ The previous constants/helper/constructor are removed. Rescue the new storage
55
+ error constants. The public `Phronomy::AgentBusyError` admission exception remains.
56
+ This is a source/API migration, not a persisted payload migration.
57
+
58
+ ## SQL implementation changes
59
+
60
+ A raw SQL backend implements `capabilities`, `transaction`, and
61
+ `assert_agent_watermark!`, and supplies all eight raw repositories to the common
62
+ Backend constructor. It exchanges `Storage::DurableRecord` and explicit ID,
63
+ revision, position, and admission metadata. It does not decode domain types.
64
+
65
+ In its transaction implementation:
66
+
67
+ 1. Check out a connection and open the database transaction as before.
68
+ 2. Bind contents, agents, journals, executions, workflow_states, handoff_states,
69
+ teams, team_executions, and the watermark object to that same connection.
70
+ 3. Construct `Storage::Repositories` with those eight keyword arguments and
71
+ `watermark:`; yield this raw view inside the database transaction block.
72
+ 4. Return the block result; propagate failures through the existing transaction
73
+ rollback path. Keep the existing handling of indeterminate commit outcomes.
74
+
75
+ `Persistence#transaction` constructs the corresponding domain facades inside
76
+ that block. SQL code no longer calls `build_transaction_view` or private
77
+ `PersistenceComposition::Repositories` or domain repository wrappers. Application/bootstrap code creates the raw SQL backend,
78
+ then passes it to `Persistence.new(backend:)`.
79
+
80
+ The SQLite and PostgreSQL implementations in `phronomy-examples` at `231d253`
81
+ use the previous SPI and require this migration. Do not use their unchanged
82
+ sources with the new core. Keep this branch's API change separate from a release
83
+ until the applications/backends to be shipped with it have also migrated.
84
+
85
+ ## Validation
86
+
87
+ Use the existing explicitly loaded shared contract suite with a composed
88
+ `persistence` value. All eight repositories must still commit or roll back
89
+ together. Validate root and transaction repository binding, CAS/admission and
90
+ watermark checks, record round trips, and codec failure rollback. Perform actual
91
+ SQL tests with the backend's supported database and driver versions; an
92
+ in-memory success does not prove SQL transaction/concurrency behavior.
93
+
94
+ ## Execution constraint errors (ADR-043)
95
+
96
+ Raw `Storage::Backend` execution repositories must report
97
+ `Storage::ActiveExecutionConflictError`, a `Storage::ConflictError` subtype, when
98
+ an existing nonterminal execution prevents another admission or an idle-only
99
+ operation for that owner. Update the same constraint branches in `save` if the
100
+ backend already checks them. Do not convert unrelated identity/revision failures.
101
+
102
+ The Agent and Team repository facades translate this subtype into the existing
103
+ `Phronomy::AgentBusyError` while preserving its message and cause. A transaction
104
+ still sees the exception before commit. Public Persistence/Agent/Team callers
105
+ keep their previous busy exception; raw backend callers must update their rescue.
106
+
107
+ Apply the new core before the migrated SQLite/PostgreSQL sources. Both examples
108
+ require the new storage constant; for coordinated source development set
109
+ `PHRONOMY_PATH` to the updated core checkout before resolving/running their
110
+ bundles. An unchanged legacy backend remains usable through the domain facade
111
+ because its old `AgentBusyError` is passed through, but it does not satisfy the
112
+ new raw conformance checks. No fallback constant aliases are supplied.
113
+
114
+ Run `a Persistence backend` from `phronomy/testing/persistence_contract`; it now
115
+ includes `storage execution constraint notifications` for both raw execution
116
+ repositories. Keep running the domain repository suites and backend concurrency
117
+ and rollback tests. No schema or serialized data migration is required.
@@ -0,0 +1,74 @@
1
+ # Storage transaction boundaries (Refactor 34)
2
+
3
+ Historical migration step. Its old raw SPI surface is superseded by the
4
+ [neutral Storage SPI 2 migration](neutral-storage-spi.md); use that guide for the
5
+ current backend contract.
6
+
7
+
8
+ Update core and the SQLite/PostgreSQL reference adapters together. No data
9
+ migration is required. The public method signatures, eight repository accessors,
10
+ required capability keys and stored record formats are unchanged.
11
+
12
+ ## Explicit nested calls
13
+
14
+ Nested `Backend#transaction` and `Persistence#transaction` calls on the same
15
+ backend and synchronous execution context now have savepoint semantics.
16
+
17
+ ```ruby
18
+ persistence.transaction do |outer|
19
+ outer.contents.put_text("keep if outer succeeds")
20
+ begin
21
+ persistence.transaction do |inner|
22
+ inner.contents.put_text("discard on inner failure")
23
+ raise "inner failure"
24
+ end
25
+ rescue RuntimeError
26
+ # Inner changes have already been rolled back. Re-read conditions needed
27
+ # for subsequent work through the valid outer scope.
28
+ outer.contents.put_text("outer may continue")
29
+ end
30
+ end
31
+ ```
32
+
33
+ Earlier SQL reference versions joined the outer scope. Catching the inner error
34
+ could preserve inner writes. Such writes are now rolled back. A successful inner
35
+ call does not commit independently; failure of the outer call rolls back both.
36
+ The same exception object is propagated after rollback, including
37
+ `ActiveRecord::Rollback`, which ActiveRecord itself normally consumes. Catch
38
+ that exception outside the Storage/Persistence block if continued execution is
39
+ intended. No separate database connection is introduced.
40
+
41
+ ## Invalid Journal batches and database failures
42
+
43
+ The SQL references now validate and serialize every record and normalize the
44
+ expected position before the first write. An invalid second record cannot leave
45
+ the first inserted with an unchanged Journal head. Record IDs from a rejected
46
+ input batch can be retried with valid data.
47
+
48
+ This is an input-validation guarantee. A database failure after writing must
49
+ escape the current transaction scope. To continue outer work, establish an
50
+ explicit inner scope before the operation, and catch outside that inner scope.
51
+ Do not catch and ignore database errors inside the failed scope. Unknown commit
52
+ outcomes still require existing reconciliation rules, not blind retries.
53
+
54
+ ## Active Agent execution updates
55
+
56
+ InMemory now enforces the same active-owner exclusion during update as SQL.
57
+ Trying to reactivate an Agent execution while a different execution for that
58
+ Agent is active raises `Storage::ActiveExecutionConflictError` at the raw boundary
59
+ and does not advance the revision or replace the record. The domain-facing
60
+ repository retains its existing error translation. Team terminal execution
61
+ reactivation remains forbidden.
62
+
63
+ ## Backend authors and remaining migration
64
+
65
+ Run `phronomy/testing/persistence_contract`, including `a Persistence backend`,
66
+ against each real backend. Explicit nested calls must preserve block results,
67
+ exception identity, inner rollback and outer atomicity across repositories.
68
+ SQL integrations additionally exercise physical constraints, concurrent writers,
69
+ connection failure and durable reload; mocked connection responses do not cover
70
+ those guarantees.
71
+
72
+ Records/Streams/Blobs, failed-view enforcement and explicit non-local block-exit
73
+ handling are later S2b work. Do not use `return` / `break` / `throw` as portable
74
+ commit controls in the current SPI. See [ADR-057](../decisions/057-storage-transaction-boundaries.md).
@@ -0,0 +1,110 @@
1
+ # VectorStore and Embeddings: asynchronous client migration
2
+
3
+ This unreleased P3 change moves the Beta asynchronous API to explicit clients.
4
+ It changes the receiver used by callers. Backend authors continue to implement
5
+ only synchronous methods; method arguments and results remain unchanged.
6
+
7
+ | Previous receiver | New receiver |
8
+ |---|---|
9
+ | `store.add_async(...)` | `async_store.add_async(...)` |
10
+ | `store.search_async(...)` | `async_store.search_async(...)` |
11
+ | `store.remove_async(...)` | `async_store.remove_async(...)` |
12
+ | `store.clear_async(...)` | `async_store.clear_async(...)` |
13
+ | `embeddings.embed_async(text, token, timeout: seconds)` | `async_embeddings.embed_async(text, token, timeout: seconds)` |
14
+
15
+ Construct the clients with `VectorStore::AsyncClient.new(backend: store)` and
16
+ `VectorStore::Embeddings::AsyncClient.new(adapter: embeddings)`. The embedding
17
+ cancellation token stays positional. Synchronous `add`, `search`, `remove`,
18
+ `clear`, `size` and `embed` stay on the existing backend objects.
19
+
20
+ `VectorStore::AsyncBackend` and inherited async methods are removed. There is
21
+ no include/prepend, backend `.async` factory, or automatic compatibility shim.
22
+ Update the receiver wherever an application previously called an async method.
23
+ The clients are public Beta API; their `async/` directories do not introduce
24
+ `Phronomy::Async` or feature-specific `Async` namespaces.
25
+
26
+ ## Complete offline example
27
+
28
+ This example uses an intentionally simple local embedding adapter to demonstrate
29
+ the API. It needs no provider key, network request, or database server. The
30
+ implementation supplies only `embed`; Phronomy supplies asynchronous execution.
31
+ Run it against a checkout containing P3, not the previously released 0.27.0 gem.
32
+
33
+ ```ruby runnable
34
+ require "phronomy"
35
+ require "json"
36
+
37
+ class KeywordEmbeddings < Phronomy::Embeddings::Base
38
+ protected
39
+
40
+ def perform_embed(text, cancellation_token = nil)
41
+ cancellation_token&.raise_if_cancelled!
42
+ words = text.downcase
43
+ [words.include?("ruby") ? 1.0 : 0.0,
44
+ words.include?("python") ? 1.0 : 0.0]
45
+ end
46
+ end
47
+
48
+ begin
49
+ store = Phronomy::VectorStore::InMemory.new(dimension: 2)
50
+ embeddings = KeywordEmbeddings.new
51
+ async_store = Phronomy::VectorStore::AsyncClient.new(backend: store)
52
+ async_embeddings = Phronomy::Embeddings::AsyncClient.new(adapter: embeddings)
53
+
54
+ {"ruby" => "Ruby guide", "python" => "Python guide"}.each do |id, title|
55
+ async_embeddings.embed_async(title).flat_map do |vector|
56
+ async_store.add_async(id: id, embedding: vector, metadata: {title: title})
57
+ end.wait_result
58
+ end
59
+
60
+ matches = async_embeddings.embed_async("Ruby").flat_map do |vector|
61
+ async_store.search_async(query_embedding: vector, k: 1)
62
+ end.wait_result
63
+ puts JSON.generate(matches)
64
+ ensure
65
+ Phronomy.reset_runtime!
66
+ end
67
+ ```
68
+
69
+ The result contains the `ruby` document. The application waits only outside
70
+ worker callbacks; `flat_map` returns the next TaskResult without blocking a
71
+ worker on another operation. `Tools::VectorSearch` continues to call synchronous
72
+ `embed` and `search` inside its existing execution boundary, so this migration
73
+ does not add nested offload work to that Tool.
74
+
75
+ ## Execution and cancellation
76
+
77
+ Both clients accept optional `pool:` injection. Usually omit it. Construction
78
+ starts no Runtime, and each operation resolves the current default pool. An
79
+ explicit pool remains caller-owned across Runtime resets; it must provide the
80
+ existing OffloadPool submit contract, including its timer service for timeouts.
81
+
82
+ Queue admission uses `on_full: :raise`. A full or stopped pool raises immediately;
83
+ an accepted operation returns the original TaskResult. Timeout includes queue
84
+ wait. Cancellation or timeout before worker pickup skips the operation; after
85
+ execution starts it settles the result without forcibly stopping I/O or undoing
86
+ backend effects. These are the existing OffloadPool semantics.
87
+
88
+ Synchronous RBS signatures accept the structural `_CancellationSignal`
89
+ interface, which requires only `raise_if_cancelled!`. Existing
90
+ `Concurrency::CancellationToken` objects still satisfy it. Async RBS signatures
91
+ live in `sig/phronomy/vector_store/async/async_client.rbs` and
92
+ `sig/phronomy/embeddings/async/async_client.rbs` and retain the full CancellationToken
93
+ and TaskResult contract needed by the execution pool. Do not substitute a
94
+ minimal synchronous signal for an async operation's full token.
95
+
96
+ ## Source ownership
97
+
98
+ The public class names below are unchanged. Their implementation files move:
99
+
100
+ | Public class | New path under `lib/phronomy/` |
101
+ |---|---|
102
+ | `VectorStore::InMemory` | `vector_store/backends/in_memory.rb` |
103
+ | `VectorStore::Pgvector` | `vector_store/backends/pgvector.rb` |
104
+ | `VectorStore::RedisSearch` | `vector_store/backends/redis_search.rb` |
105
+ | `VectorStore::Embeddings::RubyLLMEmbeddings` | `embeddings/backends/ruby_llm_embeddings.rb` |
106
+
107
+ Use `require "phronomy"` and the public constants. Direct partial-load paths are
108
+ not the public loading contract; no require shim is kept in the contract
109
+ directories. Backend Contracts have no execution or implementation dependency.
110
+ P4 Storage/ContentStore work remains pending.