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
data/lib/phronomy.rb CHANGED
@@ -13,19 +13,29 @@ loader.inflector.inflect("llm_adapter" => "LLMAdapter")
13
13
  loader.inflector.inflect("llm_operation_result" => "LLMOperationResult")
14
14
  loader.inflector.inflect("ruby_llm" => "RubyLLM")
15
15
  loader.inflector.inflect("canonical_json" => "CanonicalJSON")
16
- loader.inflector.inflect("ruby_llm_materializer" => "RubyLLMMaterializer")
17
16
  loader.inflector.inflect("llm_call_record" => "LLMCallRecord")
18
17
  loader.inflector.inflect("llm_input_manifest" => "LLMInputManifest")
19
18
  loader.inflector.inflect("llm_input_build_context" => "LLMInputBuildContext")
20
19
  loader.inflector.inflect("llm_input_patch" => "LLMInputPatch")
21
20
  loader.inflector.inflect("before_llm_input" => "BeforeLLMInput")
22
21
  # These responsibility directories do not add a public Ruby namespace.
23
- %w[common configuration engine generation llm_contract recovery].each do |directory|
22
+ %w[common configuration engine execution generation runtime_composition].each do |directory|
23
+ loader.collapse("#{__dir__}/phronomy/#{directory}")
24
+ end
25
+ # Backend contracts, execution clients and implementations have separate source
26
+ # directories, while keeping their existing feature namespace.
27
+ %w[
28
+ llm_adapter/async llm_adapter/backends
29
+ vector_store/async vector_store/backends
30
+ embeddings/async embeddings/backends
31
+ storage/async
32
+ multi_agent/runtime_binding
33
+ ].each do |directory|
24
34
  loader.collapse("#{__dir__}/phronomy/#{directory}")
25
35
  end
26
36
  # Agent responsibility directories retain the existing Agent constant names.
27
37
  %w[
28
- context_contract lifecycle execution tool_execution context_assembly
38
+ lifecycle execution tool_execution runtime_binding
29
39
  journal handoff recovery
30
40
  ].each do |directory|
31
41
  loader.collapse("#{__dir__}/phronomy/agent/#{directory}")
@@ -36,44 +46,81 @@ end
36
46
  # beside the feature they belong to, without aliases or a new partial-load API.
37
47
  %w[
38
48
  agent/api
39
- agent/lifecycle_contract
40
- filter/contract
41
- output_parser/contract
42
- persistence/api
43
- tool/contract
44
49
  workflow/execution
45
- workflow/storage_contract
46
- multi_agent/storage_contract
50
+ workflow/runtime_binding
47
51
  ].each do |directory|
48
52
  loader.push_dir("#{__dir__}/phronomy/#{directory}", namespace: Phronomy)
49
53
  end
50
54
 
51
55
  # These files wire composition, reopen namespaces, or patch a dependency.
52
56
  loader.ignore(
53
- "#{__dir__}/phronomy/configuration/global_configuration.rb",
57
+ "#{__dir__}/phronomy/persistence/persistence.rb",
58
+ "#{__dir__}/phronomy/persistence/errors.rb",
59
+ "#{__dir__}/phronomy/persistence_composition/stores.rb",
60
+ "#{__dir__}/phronomy/runtime_composition/global_configuration.rb",
54
61
  "#{__dir__}/phronomy/agent/composition",
55
62
  "#{__dir__}/phronomy/runtime_composition/agent_defaults.rb",
63
+ "#{__dir__}/phronomy/runtime_composition/generation_defaults.rb",
64
+ "#{__dir__}/phronomy/runtime_composition/evaluation_defaults.rb",
65
+ "#{__dir__}/phronomy/runtime_composition/workflow_defaults.rb",
66
+ "#{__dir__}/phronomy/runtime_composition/multi_agent_defaults.rb",
56
67
  "#{__dir__}/phronomy/runtime_composition/configuration_defaults.rb",
57
- "#{__dir__}/phronomy/runtime_composition/global_runtime.rb"
68
+ "#{__dir__}/phronomy/runtime_composition/global_runtime.rb",
69
+ "#{__dir__}/phronomy/runtime_composition/execution_defaults.rb"
58
70
  )
71
+ # Optional application integrations are loaded explicitly by their consumers.
72
+ loader.ignore("#{__dir__}/phronomy/integrations")
59
73
  # Persistence conformance support must never make production loading require RSpec.
60
74
  loader.ignore(
61
75
  "#{__dir__}/phronomy/testing/persistence_contract.rb",
62
76
  "#{__dir__}/phronomy/testing/persistence_contract"
63
77
  )
78
+ # Failure contracts can define Persistence before ordinary framework loading.
79
+ # Explicitly install its service methods without constructing a backend/Runtime.
80
+ require_relative "phronomy/persistence/persistence"
81
+ require_relative "phronomy/persistence/errors"
82
+ loader.ignore("#{__dir__}/phronomy/tool/tool_error.rb")
83
+ loader.ignore("#{__dir__}/phronomy/filter/filter_block_error.rb")
84
+ loader.ignore("#{__dir__}/phronomy/output_parser/parse_error.rb")
85
+ loader.ignore("#{__dir__}/phronomy/agent/agent_busy_error.rb")
86
+ loader.ignore("#{__dir__}/phronomy/agent/agent_purged_error.rb")
87
+ loader.ignore("#{__dir__}/phronomy/agent/stream_callback_error.rb")
88
+ loader.ignore("#{__dir__}/phronomy/agent/handoff_error.rb")
89
+ loader.ignore("#{__dir__}/phronomy/agent/agent_already_exists_error.rb")
90
+ loader.ignore("#{__dir__}/phronomy/agent/agent_not_found_error.rb")
91
+ loader.ignore("#{__dir__}/phronomy/agent/agent_unloaded_error.rb")
64
92
  loader.setup
93
+ require_relative "phronomy/persistence/transaction"
94
+ require_relative "phronomy/persistence_composition/stores"
95
+ require_relative "phronomy/tool/tool_error"
96
+ require_relative "phronomy/filter/filter_block_error"
97
+ require_relative "phronomy/output_parser/parse_error"
98
+ require_relative "phronomy/agent/agent_busy_error"
99
+ require_relative "phronomy/agent/agent_purged_error"
100
+ require_relative "phronomy/agent/stream_callback_error"
101
+ require_relative "phronomy/agent/handoff_error"
102
+ require_relative "phronomy/agent/agent_already_exists_error"
103
+ require_relative "phronomy/agent/agent_not_found_error"
104
+ require_relative "phronomy/agent/agent_unloaded_error"
65
105
 
66
106
  require_relative "phronomy/runtime_composition/configuration_defaults"
67
- require_relative "phronomy/llm_contract/token_usage"
68
- require_relative "phronomy/configuration/global_configuration"
107
+ require_relative "phronomy/llm_adapter/token_usage"
108
+ require_relative "phronomy/runtime_composition/global_configuration"
69
109
  require_relative "phronomy/runtime_composition/global_runtime"
110
+ require_relative "phronomy/runtime_composition/execution_defaults"
70
111
 
71
112
  # Explicitly install the Agent namespace extensions even if its factory
72
113
  # contract was loaded first. Composition owns both concrete binding and the
73
114
  # run_once method definition; neither is required from Agent execution files.
74
115
  require_relative "phronomy/agent/api/agent"
75
116
  require_relative "phronomy/runtime_composition/agent_defaults"
117
+ require_relative "phronomy/runtime_composition/multi_agent_defaults"
118
+ require_relative "phronomy/runtime_composition/workflow_defaults"
119
+ require_relative "phronomy/runtime_composition/generation_defaults"
120
+ require_relative "phronomy/runtime_composition/evaluation_defaults"
76
121
  require_relative "phronomy/agent/composition/run_once"
77
122
 
78
- # Load the common recovery vocabulary during ordinary application loading.
79
- require_relative "phronomy/recovery/recovery"
123
+ # Preserve ordinary boot loading of the existing recovery rules and comparisons
124
+ # while giving each definition its owning domain.
125
+ require_relative "phronomy/agent/recovery/recovery_rules"
126
+ require_relative "phronomy/persistence/snapshot_comparison"
@@ -18,32 +18,62 @@ require_relative "../lib/phronomy"
18
18
 
19
19
  PUBLIC_API_ENTRIES = [
20
20
  # Stable
21
+ Phronomy::Error,
22
+ Phronomy::AgentNotFoundError,
23
+ Phronomy::AgentUnloadedError,
24
+ Phronomy::Agent,
25
+ Phronomy::Agent::Scope,
26
+ Phronomy::Agent::ScopeCleanupError,
27
+ Phronomy::MultiAgent::TeamNotFoundError,
28
+ Phronomy::MultiAgent::TeamBusyError,
29
+ Phronomy::Embeddings::AuthenticationError,
30
+ Phronomy::Embeddings::RateLimitError,
21
31
  Phronomy::Agent::Base,
22
- Phronomy::Agent::ContextPolicy,
23
- Phronomy::Agent::ContextPolicyInput,
24
- Phronomy::Agent::ContextPolicyInput::Provenance,
25
- Phronomy::Agent::ContextPolicyInput::InstructionItem,
26
- Phronomy::Agent::ContextPolicyInput::KnowledgeItem,
27
- Phronomy::Agent::ContextPolicyInput::ToolItem,
28
- Phronomy::Agent::ContextPolicyInput::ConversationItem,
29
- Phronomy::Agent::ContextPlan,
32
+ Phronomy::Agent::ReservedExecution,
33
+ Phronomy::Agent::ExecutionObservation,
34
+ Phronomy::Agent::KnowledgeItem,
35
+ Phronomy::Agent::Retention,
36
+ Phronomy::Agent::ExecutionExtensionState,
37
+ Phronomy::Agent::ControlRequest,
38
+ Phronomy::Context::ContextPolicy,
39
+ Phronomy::Context::ContextPolicyInput,
40
+ Phronomy::Context::ContextPolicyInput::Provenance,
41
+ Phronomy::Context::ContextPolicyInput::InstructionItem,
42
+ Phronomy::Context::ContextPolicyInput::KnowledgeItem,
43
+ Phronomy::Context::ContextPolicyInput::ToolItem,
44
+ Phronomy::Context::ContextPolicyInput::ConversationItem,
45
+ Phronomy::Context::ContextPlan,
30
46
  Phronomy::InvocationContext,
31
- Phronomy::Agent::Context::Capability::Base,
47
+ Phronomy::Tool::Base,
32
48
  Phronomy::Workflow,
49
+ Phronomy::Workflow::Builder,
50
+ Phronomy::WorkflowTaskResumeError,
33
51
  Phronomy::WorkflowContext,
34
52
  Phronomy::Runnable,
35
- Phronomy::Agent::Context::Instruction::PromptTemplate,
53
+ Phronomy::Context::PromptTemplate,
36
54
  # Beta
37
- Phronomy::Agent::Handoff,
38
- Phronomy::Agent::HandoffPolicy,
55
+ Phronomy::Tool::Schema,
56
+ Phronomy::Tool::CallRequest,
57
+ Phronomy::Tool::Operation,
58
+ Phronomy::LLMAdapter::Base,
59
+ Phronomy::LLMAdapter::Request,
60
+ Phronomy::LLMAdapter::Message,
61
+ Phronomy::LLMAdapter::Response,
62
+ Phronomy::LLMAdapter::StreamChunk,
63
+ Phronomy::LLMAdapter::TokenUsage,
64
+ Phronomy::MultiAgent::Handoff,
65
+ Phronomy::MultiAgent::HandoffPolicy,
39
66
  Phronomy::MultiAgent::HandoffRunner,
40
67
  Phronomy::MultiAgent::Orchestrator,
41
68
  Phronomy::MultiAgent::TeamCoordinator,
42
69
  Phronomy::Filter::Base,
43
70
  Phronomy::Filter::PromptInjectionFilter,
71
+ Phronomy::Storage::AsyncClient,
44
72
  Phronomy::VectorStore::Base,
73
+ Phronomy::VectorStore::AsyncClient,
45
74
  Phronomy::VectorStore::InMemory,
46
- Phronomy::VectorStore::Embeddings::Base,
75
+ Phronomy::Embeddings::Base,
76
+ Phronomy::Embeddings::AsyncClient,
47
77
  Phronomy::Tracing::Base,
48
78
  Phronomy::Tracing::NullTracer,
49
79
  Phronomy::Tools::Mcp,
@@ -67,13 +97,15 @@ def snapshot_entry(klass)
67
97
  {
68
98
  "name" => klass.name,
69
99
  "type" => "module",
70
- "public_instance_methods" => own_methods
100
+ "public_instance_methods" => own_methods,
101
+ "public_class_methods" => (klass.public_methods(false) - BASELINE_CLASS_METHODS).sort
71
102
  }
72
103
  else
73
104
  internal_context_methods = (klass == Phronomy::InvocationContext) ?
74
105
  %i[__bind_execution __execution_scope] : []
75
106
  instance_methods = (klass.public_instance_methods - BASELINE_INSTANCE_METHODS - internal_context_methods).sort
76
- class_methods = (klass.public_methods(false) - BASELINE_CLASS_METHODS).sort
107
+ internal_class_methods = (klass == Phronomy::Storage::AsyncClient) ? %i[submit] : []
108
+ class_methods = (klass.public_methods(false) - BASELINE_CLASS_METHODS - internal_class_methods).sort
77
109
  {
78
110
  "name" => klass.name,
79
111
  "type" => "class",
@@ -1,38 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Extracts every ```ruby ... ``` block from README.md and runs `ruby -c` on each.
4
- # Exits non-zero if any block has a syntax error.
5
-
3
+ # Check all Ruby fences, including executable examples, in the entry documents.
6
4
  require "tempfile"
7
5
  require "open3"
8
-
9
- readme_path = File.expand_path("../README.md", __dir__)
10
- readme = File.read(readme_path)
11
- blocks = readme.scan(/^```ruby\n(.*?)^```/m).map.with_index(1) { |(code), i| [i, code] }
12
-
13
- puts "Checking #{blocks.size} Ruby code blocks in README.md..."
6
+ require_relative "check_readme_runnable"
14
7
 
15
8
  failures = []
16
-
17
- blocks.each do |index, code|
18
- Tempfile.create(["readme_block_#{index}", ".rb"]) do |f|
19
- f.write(code)
20
- f.flush
21
- stdout, status = Open3.capture2e("ruby", "-c", f.path)
22
- if status.success?
23
- puts " OK block ##{index}"
24
- else
25
- failures << index
26
- puts " FAIL block ##{index}"
27
- puts stdout.gsub(f.path, "block ##{index}")
9
+ count = 0
10
+ paths = ARGV.empty? ? RunnableDocumentation::PATHS : ARGV
11
+ paths.each do |relative|
12
+ text = File.read(File.expand_path(relative, RunnableDocumentation::ROOT))
13
+ text.to_enum(:scan, /^```ruby(?: runnable)?\n(.*?)^```/m).each do
14
+ match = Regexp.last_match
15
+ line = text[0...match.begin(1)].count("\n") + 1
16
+ label = "#{relative}:#{line}"
17
+ count += 1
18
+ Tempfile.create(["documentation_block", ".rb"]) do |file|
19
+ file.write(match[1])
20
+ file.flush
21
+ out, status = Open3.capture2e(RbConfig.ruby, "-c", file.path)
22
+ if status.success?
23
+ puts "OK #{label}"
24
+ else
25
+ failures << label
26
+ puts "FAIL #{label}"
27
+ puts out.gsub(file.path, label)
28
+ end
28
29
  end
29
30
  end
30
31
  end
31
-
32
- if failures.empty?
33
- puts "All #{blocks.size} Ruby code blocks passed syntax check."
34
- exit 0
35
- else
36
- puts "\n#{failures.size} block(s) failed syntax check: #{failures.join(", ")}"
37
- exit 1
38
- end
32
+ puts "#{count} Ruby blocks; #{failures.size} syntax failures"
33
+ exit(failures.empty? ? 0 : 1)
@@ -1,101 +1,112 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # scripts/check_readme_runnable.rb
4
- #
5
- # Extracts ```ruby runnable blocks from README.md and executes each in an
6
- # isolated subprocess with a fake LLM stub to catch API drift.
7
- #
8
- # Any block that raises NoMethodError / ArgumentError / NameError causes a
9
- # non-zero exit, failing the CI step.
10
- #
11
- # Usage (from the phronomy/ root):
12
- # bundle exec ruby scripts/check_readme_runnable.rb
13
-
3
+ # Runs annotated, self-contained examples through the real public API.
4
+ # Only the external LLM adapter is replaced. Each block has its own process,
5
+ # configuration and Runtime; an accidental network request fails immediately.
6
+ # Usage: bundle exec ruby scripts/check_readme_runnable.rb [markdown paths...]
14
7
  require "tempfile"
15
8
  require "open3"
16
9
 
17
- REPO_ROOT = File.expand_path("..", __dir__)
18
- README_PATH = File.join(REPO_ROOT, "README.md")
19
-
20
- # Injected before every runnable block.
21
- # Uses the Gemfile of this project so subprocesses can load phronomy.
22
- PREAMBLE = <<~RUBY
23
- # frozen_string_literal: true
24
- # --- CI preamble: stub LLM calls so no real network requests are made ---
25
- ENV["BUNDLE_GEMFILE"] ||= "#{File.join(REPO_ROOT, "Gemfile")}"
26
- require "bundler/setup"
27
- require "phronomy"
10
+ module RunnableDocumentation
11
+ ROOT = File.expand_path("..", __dir__)
12
+ PATHS = %w[README.md docs/getting-started.md docs/application-recipes.md docs/workflow-completion.md].freeze
13
+
14
+ PREAMBLE = <<~RUBY
15
+ require "bundler/setup"
16
+ require "phronomy"
17
+ require "webmock"
18
+ require "timeout"
19
+ WebMock.enable!
20
+ WebMock.disable_net_connect!
21
+
22
+ class DocumentationLLM < Phronomy::LLMAdapter::Base
23
+ protected
24
+
25
+ def perform_complete(request, cancellation_token:)
26
+ previous = request.messages.last
27
+ if previous&.role == :tool
28
+ return Phronomy::LLMAdapter::Response.new(content: previous.content)
29
+ end
28
30
 
29
- # Patch invoke methods to return canned responses instead of calling the LLM.
30
- module Phronomy
31
- module Agent
32
- # Prepend overrides AsyncEventApi (which is also prepended) so invoke
33
- # returns a canned response without triggering the EventLoop.
34
- module CiInvokeStub
35
- def invoke(input = nil, **)
36
- {output: "ci-stub-output", messages: []}
31
+ search = request.tools.find do |tool|
32
+ tool.fetch("parameters_schema").fetch("properties", {}).key?("query")
37
33
  end
34
+ if search
35
+ return Phronomy::LLMAdapter::Response.new(tool_calls: [
36
+ Phronomy::Tool::CallRequest.new(
37
+ id: SecureRandom.uuid, name: search.fetch("name"),
38
+ arguments: {"query" => "Ruby AI frameworks"}
39
+ )
40
+ ])
41
+ end
42
+
43
+ Phronomy::LLMAdapter::Response.new(content: "ci-stub-output")
38
44
  end
39
- Base.prepend(CiInvokeStub)
40
45
 
41
- class Runner
42
- def invoke(input = nil, **)
43
- {output: "ci-stub-output", agent: nil, messages: []}
44
- end
46
+ def perform_stream(request, cancellation_token:)
47
+ response = perform_complete(request, cancellation_token: cancellation_token)
48
+ yield Phronomy::LLMAdapter::StreamChunk.new(content: response.content) if response.content
49
+ response
45
50
  end
46
51
  end
52
+ RUBY
47
53
 
48
- module Chain
49
- class LLMChain
50
- def invoke(vars = {})
51
- "ci-stub-chain"
52
- end
53
- end
54
+ def self.blocks(path)
55
+ text = File.read(path)
56
+ text.to_enum(:scan, /^```ruby runnable\n(.*?)^```/m).map do
57
+ match = Regexp.last_match
58
+ [text[0...match.begin(1)].count("\n") + 1, match[1]]
54
59
  end
55
60
  end
56
- # --- end CI preamble ---
57
-
58
- RUBY
59
-
60
- readme = File.read(README_PATH)
61
61
 
62
- # Match opening fence with 'runnable' annotation: ```ruby runnable
63
- blocks = readme.scan(/^```ruby runnable\n(.*?)^```/m).map.with_index(1) { |(code), i| [i, code] }
64
-
65
- if blocks.empty?
66
- puts "No 'ruby runnable' blocks found in README.md."
67
- exit 0
68
- end
69
-
70
- puts "Checking #{blocks.size} runnable Ruby block(s) in README.md..."
71
-
72
- failures = []
73
-
74
- blocks.each do |index, code|
75
- Tempfile.create(["readme_runnable_#{index}", ".rb"]) do |f|
76
- f.write(PREAMBLE)
77
- f.write(code)
78
- f.flush
79
-
80
- out, err, status = Open3.capture3(RbConfig.ruby, f.path)
81
- combined = (out + err).gsub(f.path, "block ##{index}")
82
-
83
- if status.success?
84
- puts " OK block ##{index}"
85
- else
86
- failures << index
87
- puts " FAIL block ##{index}"
88
- # Print at most 15 lines of output to keep CI logs readable.
89
- puts combined.lines.first(15).join
62
+ def self.check(paths = PATHS, output: $stdout)
63
+ failures = []
64
+ count = 0
65
+ paths.each do |relative|
66
+ path = File.expand_path(relative, ROOT)
67
+ examples = blocks(path)
68
+ if examples.empty?
69
+ failures << relative
70
+ output.puts "FAIL #{relative}: no ruby runnable blocks"
71
+ end
72
+ examples.each do |line, code|
73
+ count += 1
74
+ label = "#{relative}:#{line}"
75
+ Tempfile.create(["phronomy_documentation", ".rb"]) do |file|
76
+ file.write(PREAMBLE)
77
+ file.write(<<~RUBY)
78
+ Phronomy.with_configuration do |configuration|
79
+ configuration.llm_adapter = DocumentationLLM.new
80
+ begin
81
+ Timeout.timeout(20) do
82
+ eval(#{code.dump}, TOPLEVEL_BINDING, #{path.dump}, #{line})
83
+ end
84
+ ensure
85
+ Phronomy::Runtime.reset_default!(timeout: 5)
86
+ end
87
+ end
88
+ RUBY
89
+ file.flush
90
+ out, err, status = Open3.capture3(
91
+ {"BUNDLE_GEMFILE" => File.join(ROOT, "Gemfile")},
92
+ RbConfig.ruby, file.path, chdir: ROOT
93
+ )
94
+ if status.success?
95
+ output.puts "OK #{label}"
96
+ else
97
+ failures << label
98
+ output.puts "FAIL #{label}"
99
+ output.puts (out + err).gsub(file.path, label).lines.first(15).join
100
+ end
101
+ end
102
+ end
90
103
  end
104
+ output.puts "#{count} runnable examples; #{failures.size} failures"
105
+ failures.empty?
91
106
  end
92
107
  end
93
108
 
94
- puts
95
- if failures.empty?
96
- puts "All #{blocks.size} runnable block(s) passed."
97
- exit 0
98
- else
99
- puts "#{failures.size} block(s) failed: #{failures.join(", ")}"
100
- exit 1
109
+ if $PROGRAM_NAME == __FILE__
110
+ paths = ARGV.empty? ? RunnableDocumentation::PATHS : ARGV
111
+ exit(RunnableDocumentation.check(paths) ? 0 : 1)
101
112
  end
@@ -0,0 +1,19 @@
1
+ module Phronomy
2
+ module Agent
3
+ class Settings
4
+ def self.install_provider: () { () -> Settings } -> void
5
+ def self.current: () -> Settings
6
+ def initialize: (llm_adapter: LLMAdapter::Base?, authorization_timeout: Numeric?, stream_callback_error_policy: Symbol) -> void
7
+ attr_accessor default_model: String?
8
+ attr_accessor before_llm_input: _BeforeLLMInputHook?
9
+ attr_accessor agent_store: Store?
10
+ attr_accessor llm_adapter: LLMAdapter::Base?
11
+ attr_accessor authorization_timeout: Numeric?
12
+ attr_accessor stream_callback_error_policy: Symbol
13
+ end
14
+ end
15
+
16
+ class Configuration
17
+ attr_reader __agent_settings: Agent::Settings
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Phronomy
2
+ # Internal Engine-facing settings; application-specific types do not belong here.
3
+ class RuntimeSettings
4
+ def self.install_provider: () { () -> RuntimeSettings } -> void
5
+ def self.current: () -> RuntimeSettings
6
+ def initialize: () -> void
7
+ attr_accessor logger: untyped
8
+ attr_accessor event_loop_stop_grace_seconds: Numeric
9
+ attr_accessor event_loop_starvation_threshold_seconds: Numeric?
10
+ attr_accessor event_loop_dispatch_threshold_seconds: Numeric?
11
+ attr_accessor offload_pool_size: Integer
12
+ attr_accessor offload_queue_size: Integer
13
+ attr_accessor authorization_pool_size: Integer
14
+ attr_accessor authorization_queue_size: Integer
15
+ end
16
+
17
+ class Configuration
18
+ attr_reader __runtime_settings: RuntimeSettings
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ # Framework-internal API. Loaded by -I sig; not exported by gem library loading.
2
+ module Phronomy
3
+ module LLMAdapter
4
+ class AsyncClient
5
+ def initialize: (adapter: Base, ?pool: untyped, ?submitter: _ExecutionSubmitter) -> void
6
+ def complete_async: (Request request, ?cancellation_token: Concurrency::CancellationToken?, ?pool: untyped) -> TaskResult[Response]
7
+ def stream_async: (Request request, ?cancellation_token: Concurrency::CancellationToken?, ?pool: untyped) { (StreamChunk chunk) -> void } -> TaskResult[Response]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Phronomy
2
+ module MultiAgent
3
+ class Store
4
+ def self.install_configured_provider: () { () -> Store? } -> void
5
+ def self.configured: () -> Store?
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Phronomy
2
+ class Persistence
3
+ module StorageBoundary
4
+ def self.call: [T] () { () -> T } -> T
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Phronomy
2
+ module Tool
3
+ class Settings
4
+ def self.install_provider: () { () -> Settings } -> void
5
+ def self.current: () -> Settings
6
+ attr_accessor max_result_size: Integer?
7
+ end
8
+ end
9
+
10
+ class Configuration
11
+ attr_reader __tool_settings: Tool::Settings
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Phronomy
2
+ module Tracing
3
+ class Settings
4
+ def self.install_provider: () { () -> Settings } -> void
5
+ def self.current: () -> Settings
6
+ def initialize: (tracer: Tracing::Base?) -> void
7
+ attr_accessor tracer: Tracing::Base?
8
+ attr_accessor trace_pii: bool
9
+ end
10
+ end
11
+
12
+ class Configuration
13
+ attr_reader __tracing_settings: Tracing::Settings
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Phronomy
2
+ class WorkflowSettings
3
+ def self.install_provider: () { () -> WorkflowSettings } -> void
4
+ def self.current: () -> WorkflowSettings
5
+ def initialize: (recursion_limit: Integer) -> void
6
+ attr_accessor recursion_limit: Integer
7
+ attr_accessor workflow_store: _WorkflowStateRepository?
8
+ end
9
+
10
+ class Configuration
11
+ attr_reader __workflow_settings: WorkflowSettings
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module Phronomy
2
+ module Agent
3
+ # Coordination owns reservation semantics; Agent owns the acceptance operation.
4
+ interface _AdmissionOwner
5
+ def admit: (Admission admission) -> void
6
+ end
7
+
8
+ class Admission
9
+ attr_reader agent_id: String
10
+ attr_reader execution_id: String
11
+ attr_reader correlation: Hash[String, json_value]?
12
+ def initialize: (persistence: Store, root: untyped, input: String,
13
+ config: Hash[Symbol, untyped], preparation_metadata: Hash[String, untyped]) -> void
14
+ def accept: () -> nil
15
+ def accept_in: (::Phronomy::Persistence::Transaction scope) -> nil
16
+ def result: () -> [untyped, untyped]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module Phronomy
2
+ class AgentNotFoundError < Phronomy::Persistence::NotFoundError
3
+ attr_reader agent_id: String
4
+ def initialize: (agent_id: untyped) -> void
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Phronomy
2
+ class AgentUnloadedError < Phronomy::Error
3
+ attr_reader agent_id: String
4
+ def initialize: (agent_id: String) -> void
5
+ end
6
+ end