phronomy 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +9 -9
  3. data/CHANGELOG.md +52 -0
  4. data/CONTRIBUTING.md +8 -8
  5. data/README.md +28 -7
  6. data/benchmark/bench_agent_invoke.rb +25 -50
  7. data/benchmark/bench_context_assembler.rb +14 -11
  8. data/benchmark/bench_regression.rb +1 -1
  9. data/benchmark/bench_tool_schema.rb +1 -1
  10. data/docs/application-recipes.md +229 -0
  11. data/docs/architecture/agent-chat-and-state-ownership.md +7 -1
  12. data/docs/architecture/agent-transition-ownership.md +13 -89
  13. data/docs/architecture/backend-groups.md +152 -0
  14. data/docs/architecture/before-llm-input.md +3 -3
  15. data/docs/architecture/context-management.md +1 -1
  16. data/docs/architecture/dx05-agent-scope.md +119 -0
  17. data/docs/architecture/dx05-workflow-task-state.md +134 -0
  18. data/docs/architecture/error-api-review.md +245 -0
  19. data/docs/architecture/execution-abstraction-review.md +88 -0
  20. data/docs/architecture/execution-boundaries.md +28 -0
  21. data/docs/architecture/execution-metadata-and-values.md +6 -0
  22. data/docs/architecture/multi-agent-handoff.md +6 -5
  23. data/docs/architecture/persistence.md +27 -9
  24. data/docs/architecture/r8-unit1.md +104 -0
  25. data/docs/architecture/r8-unit10.md +72 -0
  26. data/docs/architecture/r8-unit11.md +71 -0
  27. data/docs/architecture/r8-unit12.md +67 -0
  28. data/docs/architecture/r8-unit13.md +61 -0
  29. data/docs/architecture/r8-unit14.md +72 -0
  30. data/docs/architecture/r8-unit15.md +65 -0
  31. data/docs/architecture/r8-unit16.md +54 -0
  32. data/docs/architecture/r8-unit17.md +73 -0
  33. data/docs/architecture/r8-unit18.md +92 -0
  34. data/docs/architecture/r8-unit19.md +61 -0
  35. data/docs/architecture/r8-unit2.md +55 -0
  36. data/docs/architecture/r8-unit20.md +51 -0
  37. data/docs/architecture/r8-unit21.md +79 -0
  38. data/docs/architecture/r8-unit22.md +74 -0
  39. data/docs/architecture/r8-unit23.md +81 -0
  40. data/docs/architecture/r8-unit3.md +130 -0
  41. data/docs/architecture/r8-unit4.md +79 -0
  42. data/docs/architecture/r8-unit5.md +115 -0
  43. data/docs/architecture/r8-unit6.md +71 -0
  44. data/docs/architecture/r8-unit7.md +70 -0
  45. data/docs/architecture/r8-unit8.md +78 -0
  46. data/docs/architecture/r8-unit9.md +73 -0
  47. data/docs/architecture/refactoring-closure.md +10 -1
  48. data/docs/architecture/remaining-refactoring-plan.md +16 -0
  49. data/docs/architecture/storage-execution-boundaries.md +54 -0
  50. data/docs/architecture/tool-schema-recording-gap.md +6 -0
  51. data/docs/architecture/tracing.md +1 -1
  52. data/docs/architecture/workflow-terminal-ownership-design.md +2 -2
  53. data/docs/architecture.md +24 -11
  54. data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
  55. data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
  56. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +2 -0
  57. data/docs/decisions/031-durable-multi-agent-coordination.md +2 -0
  58. data/docs/decisions/032-storage-backend-composition.md +5 -0
  59. data/docs/decisions/034-handoff-runner-coordination-ownership.md +2 -0
  60. data/docs/decisions/035-tool-executor-capability-ownership.md +1 -1
  61. data/docs/decisions/038-responsibility-based-source-layout.md +14 -0
  62. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +8 -0
  63. data/docs/decisions/040-configuration-default-composition.md +12 -1
  64. data/docs/decisions/045-worker-input-restriction-ownership.md +4 -0
  65. data/docs/decisions/051-execution-outcome-worker-ownership.md +2 -0
  66. data/docs/decisions/056-workflow-terminal-policy-ownership.md +1 -1
  67. data/docs/decisions/058-neutral-storage-primitives.md +5 -0
  68. data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
  69. data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
  70. data/docs/decisions/061-persistence-failure-contracts.md +89 -0
  71. data/docs/decisions/062-content-store-service.md +52 -0
  72. data/docs/decisions/063-execution-contracts-and-services.md +88 -0
  73. data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
  74. data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
  75. data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
  76. data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
  77. data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
  78. data/docs/decisions/README.md +18 -1
  79. data/docs/execution-boundaries-preview.md +45 -0
  80. data/docs/failure-reason-codes.md +45 -0
  81. data/docs/features.md +12 -4
  82. data/docs/getting-started.md +52 -48
  83. data/docs/migrations/0.22.md +2 -2
  84. data/docs/migrations/durable-semantic-coordination-v2.md +2 -0
  85. data/docs/migrations/handoff-runner-multi-agent.md +2 -0
  86. data/docs/migrations/persistence-failure-contracts.md +67 -0
  87. data/docs/migrations/r8-unit10.md +36 -0
  88. data/docs/migrations/r8-unit11.md +33 -0
  89. data/docs/migrations/r8-unit12.md +31 -0
  90. data/docs/migrations/r8-unit13.md +36 -0
  91. data/docs/migrations/r8-unit14.md +31 -0
  92. data/docs/migrations/r8-unit15.md +31 -0
  93. data/docs/migrations/r8-unit16.md +26 -0
  94. data/docs/migrations/r8-unit17.md +28 -0
  95. data/docs/migrations/r8-unit18.md +29 -0
  96. data/docs/migrations/r8-unit19.md +28 -0
  97. data/docs/migrations/r8-unit20.md +24 -0
  98. data/docs/migrations/r8-unit21.md +28 -0
  99. data/docs/migrations/r8-unit22.md +29 -0
  100. data/docs/migrations/r8-unit23.md +20 -0
  101. data/docs/migrations/r8-unit4.md +67 -0
  102. data/docs/migrations/r8-unit5.md +75 -0
  103. data/docs/migrations/r8-unit6.md +109 -0
  104. data/docs/migrations/r8-unit7.md +31 -0
  105. data/docs/migrations/r8-unit8.md +33 -0
  106. data/docs/migrations/r8-unit9.md +28 -0
  107. data/docs/migrations/storage-async-client.md +103 -0
  108. data/docs/migrations/vector-async-clients.md +110 -0
  109. data/docs/ordered-event-delivery.md +54 -0
  110. data/docs/persistence-backends.md +38 -21
  111. data/docs/runtime-and-concurrency.md +26 -1
  112. data/docs/workflow-completion.md +92 -0
  113. data/gemfiles/http_minimum.gemfile +5 -0
  114. data/lib/phronomy/agent/admission.rb +78 -0
  115. data/lib/phronomy/agent/{lifecycle_contract/agent_already_exists_error.rb → agent_already_exists_error.rb} +1 -1
  116. data/lib/phronomy/agent/{lifecycle_contract/agent_busy_error.rb → agent_busy_error.rb} +1 -1
  117. data/lib/phronomy/agent/agent_not_found_error.rb +16 -0
  118. data/lib/phronomy/agent/{lifecycle_contract/agent_purged_error.rb → agent_purged_error.rb} +1 -1
  119. data/lib/phronomy/agent/agent_unloaded_error.rb +14 -0
  120. data/lib/phronomy/agent/api/agent.rb +13 -0
  121. data/lib/phronomy/{recovery → agent/api}/execution_rehydration_required_error.rb +1 -1
  122. data/lib/phronomy/agent/async_event_api.rb +132 -103
  123. data/lib/phronomy/agent/base.rb +146 -113
  124. data/lib/phronomy/agent/before_llm_input.rb +70 -0
  125. data/lib/phronomy/agent/composition/run_once.rb +1 -1
  126. data/lib/phronomy/agent/{context_assembly/context_candidate_resolver.rb → context_candidate_resolver.rb} +2 -2
  127. data/lib/phronomy/agent/{context_assembly/context_assembler.rb → context_preparation.rb} +35 -221
  128. data/lib/phronomy/agent/control_request.rb +21 -0
  129. data/lib/phronomy/agent/execution/agent_execution.rb +1 -1
  130. data/lib/phronomy/agent/execution/agent_invocation.rb +27 -53
  131. data/lib/phronomy/agent/execution/approval_resume_commit.rb +1 -1
  132. data/lib/phronomy/agent/execution/dispatch_preparation.rb +17 -127
  133. data/lib/phronomy/agent/execution/exact_execution.rb +55 -32
  134. data/lib/phronomy/agent/execution/execution_cancellation.rb +8 -4
  135. data/lib/phronomy/agent/execution/execution_coordinator.rb +229 -407
  136. data/lib/phronomy/agent/execution/execution_metadata.rb +1 -0
  137. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +71 -127
  138. data/lib/phronomy/agent/execution/execution_registry.rb +6 -2
  139. data/lib/phronomy/agent/execution/execution_session_runner.rb +22 -27
  140. data/lib/phronomy/agent/execution/initial_preparation.rb +19 -120
  141. data/lib/phronomy/agent/execution/{agent_invocation_session_builder.rb → invocation_actions.rb} +54 -194
  142. data/lib/phronomy/agent/execution/invocation_transitions.rb +39 -1
  143. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +8 -11
  144. data/lib/phronomy/agent/execution_change.rb +161 -0
  145. data/lib/phronomy/agent/execution_environment.rb +36 -0
  146. data/lib/phronomy/agent/execution_extension_state.rb +21 -0
  147. data/lib/phronomy/agent/execution_observation.rb +35 -0
  148. data/lib/phronomy/agent/filterable.rb +188 -0
  149. data/lib/phronomy/agent/handoff/{handoff_context.rb → transfer_context.rb} +4 -4
  150. data/lib/phronomy/agent/handoff/{handoff_projection.rb → transfer_projection.rb} +14 -33
  151. data/lib/phronomy/{llm_contract/transport_error.rb → agent/handoff_error.rb} +1 -1
  152. data/lib/phronomy/agent/journal/journal_projection.rb +1 -1
  153. data/lib/phronomy/agent/knowledge_item.rb +13 -0
  154. data/lib/phronomy/agent/lifecycle/agent_root.rb +1 -1
  155. data/lib/phronomy/agent/lifecycle/lifetime_api.rb +76 -0
  156. data/lib/phronomy/agent/lifecycle/operation_lease.rb +33 -0
  157. data/lib/phronomy/agent/lifecycle/operation_result.rb +53 -0
  158. data/lib/phronomy/agent/lifecycle/ownership_registry.rb +117 -31
  159. data/lib/phronomy/agent/lifecycle/scope.rb +198 -0
  160. data/lib/phronomy/agent/lifecycle/scope_cleanup_error.rb +19 -0
  161. data/lib/phronomy/agent/lifecycle/unload_transition.rb +78 -0
  162. data/lib/phronomy/agent/persistence/agent_repository.rb +29 -21
  163. data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
  164. data/lib/phronomy/agent/persistence/codec.rb +1 -21
  165. data/lib/phronomy/agent/persistence/execution_repository.rb +57 -41
  166. data/lib/phronomy/agent/persistence/journal_repository.rb +27 -18
  167. data/lib/phronomy/agent/persistence/records.rb +33 -0
  168. data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
  169. data/lib/phronomy/agent/persistence/storage_schema.rb +7 -2
  170. data/lib/phronomy/agent/persistence/watermark.rb +13 -11
  171. data/lib/phronomy/agent/recovery/invocation_restorer.rb +13 -21
  172. data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +13 -12
  173. data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +34 -34
  174. data/lib/phronomy/agent/recovery/recovery_coordinator/resolution.rb +33 -39
  175. data/lib/phronomy/agent/recovery/recovery_coordinator.rb +28 -25
  176. data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
  177. data/lib/phronomy/agent/recovery/recovery_support.rb +10 -19
  178. data/lib/phronomy/agent/reserved_execution.rb +16 -0
  179. data/lib/phronomy/agent/retention.rb +17 -0
  180. data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
  181. data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
  182. data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
  183. data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
  184. data/lib/phronomy/agent/{context_assembly/ruby_llm_materializer.rb → runtime_input.rb} +18 -35
  185. data/lib/phronomy/agent/{context_assembly/saved_context_reader.rb → saved_context_reader.rb} +6 -4
  186. data/lib/phronomy/agent/settings.rb +47 -0
  187. data/lib/phronomy/agent/{context_assembly/state_writer.rb → state_writer.rb} +4 -3
  188. data/lib/phronomy/agent/store.rb +253 -0
  189. data/lib/phronomy/agent/{lifecycle_contract/stream_callback_error.rb → stream_callback_error.rb} +3 -3
  190. data/lib/phronomy/agent/tool_execution/tool_binding.rb +4 -64
  191. data/lib/phronomy/agent/tool_execution/tool_invocation.rb +50 -219
  192. data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
  193. data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
  194. data/lib/phronomy/common/error.rb +65 -1
  195. data/lib/phronomy/configuration/runtime_settings.rb +49 -0
  196. data/lib/phronomy/content_store/base.rb +7 -2
  197. data/lib/phronomy/content_store/storage_schema.rb +1 -0
  198. data/lib/phronomy/content_store/stored_contents.rb +2 -1
  199. data/lib/phronomy/context/assembly.rb +195 -0
  200. data/lib/phronomy/{llm_contract/context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +3 -1
  201. data/lib/phronomy/context/candidate.rb +51 -0
  202. data/lib/phronomy/context/constraint.rb +47 -0
  203. data/lib/phronomy/{agent/context_contract → context}/context_plan.rb +1 -1
  204. data/lib/phronomy/{agent/context_contract → context}/context_plan_validator.rb +3 -3
  205. data/lib/phronomy/{agent/context_contract → context}/context_policy.rb +1 -1
  206. data/lib/phronomy/{agent/context_contract → context}/context_policy_input.rb +1 -1
  207. data/lib/phronomy/{agent/context_assembly → context}/context_policy_input_builder.rb +1 -1
  208. data/lib/phronomy/context/default_policy.rb +140 -0
  209. data/lib/phronomy/context/final_budget_validator.rb +33 -0
  210. data/lib/phronomy/{agent/context_contract → context}/llm_input_build_context.rb +1 -1
  211. data/lib/phronomy/{agent/context_contract → context}/llm_input_manifest.rb +19 -19
  212. data/lib/phronomy/{agent/context_contract → context}/llm_input_patch.rb +1 -1
  213. data/lib/phronomy/context/manifest_error.rb +10 -0
  214. data/lib/phronomy/context/prompt_template.rb +98 -0
  215. data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
  216. data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
  217. data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
  218. data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
  219. data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
  220. data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
  221. data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
  222. data/lib/phronomy/embeddings/async/async_client.rb +44 -0
  223. data/lib/phronomy/embeddings/authentication_error.rb +11 -0
  224. data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +52 -0
  225. data/lib/phronomy/embeddings/base.rb +43 -0
  226. data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
  227. data/lib/phronomy/embeddings/rate_limit_error.rb +11 -0
  228. data/lib/phronomy/embeddings/transport_error.rb +11 -0
  229. data/lib/phronomy/engine/concurrency/offload_pool.rb +36 -21
  230. data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
  231. data/lib/phronomy/engine/diagnostics.rb +1 -1
  232. data/lib/phronomy/engine/event_loop.rb +7 -7
  233. data/lib/phronomy/engine/execution_binding.rb +23 -0
  234. data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
  235. data/lib/phronomy/engine/fsm_protocol.rb +1 -6
  236. data/lib/phronomy/engine/fsm_session.rb +3 -3
  237. data/lib/phronomy/engine/metrics.rb +16 -14
  238. data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
  239. data/lib/phronomy/engine/runtime.rb +25 -12
  240. data/lib/phronomy/engine/terminal_decision.rb +7 -0
  241. data/lib/phronomy/execution/async_operation.rb +41 -0
  242. data/lib/phronomy/{engine → execution}/blocking.rb +2 -2
  243. data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +1 -1
  244. data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
  245. data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
  246. data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
  247. data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
  248. data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
  249. data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
  250. data/lib/phronomy/{engine → execution}/execution.rb +61 -27
  251. data/lib/phronomy/{engine → execution}/execution_cancellation_error.rb +2 -2
  252. data/lib/phronomy/execution/execution_receiver.rb +78 -0
  253. data/lib/phronomy/execution/execution_scope_state.rb +35 -0
  254. data/lib/phronomy/{engine → execution}/execution_timeout_error.rb +2 -2
  255. data/lib/phronomy/{engine → execution}/invocation_context.rb +0 -15
  256. data/lib/phronomy/execution/invocation_controls.rb +73 -0
  257. data/lib/phronomy/execution/runnable.rb +24 -0
  258. data/lib/phronomy/{engine → execution}/task_result.rb +9 -4
  259. data/lib/phronomy/execution/wait_policy.rb +24 -0
  260. data/lib/phronomy/filter/{contract/filter_block_error.rb → filter_block_error.rb} +3 -3
  261. data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
  262. data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
  263. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +2 -2
  264. data/lib/phronomy/generation/generator_verifier.rb +7 -7
  265. data/lib/phronomy/generation/low_confidence_error.rb +2 -2
  266. data/lib/phronomy/integrations/ordered_event_delivery.rb +208 -0
  267. data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
  268. data/lib/phronomy/{llm_contract → llm_adapter}/authentication_error.rb +3 -1
  269. data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
  270. data/lib/phronomy/llm_adapter/base.rb +49 -68
  271. data/lib/phronomy/{llm_contract → llm_adapter}/context_length_error.rb +3 -1
  272. data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
  273. data/lib/phronomy/llm_adapter/message.rb +62 -0
  274. data/lib/phronomy/{llm_contract → llm_adapter}/rate_limit_error.rb +3 -1
  275. data/lib/phronomy/llm_adapter/request.rb +79 -0
  276. data/lib/phronomy/llm_adapter/response.rb +36 -0
  277. data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
  278. data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
  279. data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
  280. data/lib/phronomy/llm_adapter.rb +3 -16
  281. data/lib/phronomy/multi_agent/admission_registry.rb +1 -8
  282. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
  283. data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
  284. data/lib/phronomy/{agent/handoff → multi_agent}/handoff.rb +2 -2
  285. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_capability_factory.rb +21 -2
  286. data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
  287. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_policy.rb +1 -1
  288. data/lib/phronomy/multi_agent/handoff_runner.rb +77 -100
  289. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_state.rb +1 -1
  290. data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
  291. data/lib/phronomy/multi_agent/persistence/codec.rb +20 -0
  292. data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
  293. data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
  294. data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
  295. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +60 -44
  296. data/lib/phronomy/multi_agent/persistence/team_repository.rb +29 -21
  297. data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
  298. data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
  299. data/lib/phronomy/multi_agent/shared_state.rb +2 -2
  300. data/lib/phronomy/multi_agent/store.rb +156 -0
  301. data/lib/phronomy/multi_agent/team_busy_error.rb +18 -0
  302. data/lib/phronomy/multi_agent/team_coordinator.rb +99 -77
  303. data/lib/phronomy/multi_agent/team_not_found_error.rb +18 -0
  304. data/lib/phronomy/multi_agent/team_ownership_registry.rb +2 -12
  305. data/lib/phronomy/output_parser/parse_error.rb +7 -0
  306. data/lib/phronomy/persistence/content_repository.rb +26 -0
  307. data/lib/phronomy/persistence/errors.rb +16 -0
  308. data/lib/phronomy/persistence/migration/initial_format_migration.rb +2 -2
  309. data/lib/phronomy/persistence/persistence.rb +23 -0
  310. data/lib/phronomy/persistence/save_outcome.rb +24 -0
  311. data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
  312. data/lib/phronomy/persistence/storage_boundary.rb +32 -0
  313. data/lib/phronomy/persistence/transaction.rb +86 -0
  314. data/lib/phronomy/persistence_composition/storage_schema.rb +9 -4
  315. data/lib/phronomy/persistence_composition/stores.rb +34 -0
  316. data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
  317. data/lib/phronomy/runtime_composition/agent_defaults.rb +5 -1
  318. data/lib/phronomy/runtime_composition/configuration.rb +146 -0
  319. data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
  320. data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
  321. data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
  322. data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
  323. data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
  324. data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
  325. data/lib/phronomy/storage/async/async_client.rb +60 -0
  326. data/lib/phronomy/storage/backend.rb +8 -2
  327. data/lib/phronomy/storage/condition_failed_error.rb +2 -2
  328. data/lib/phronomy/storage/unique_constraint_error.rb +2 -2
  329. data/lib/phronomy/testing/eval/metrics.rb +1 -1
  330. data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
  331. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +2 -2
  332. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +6 -6
  333. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +55 -52
  334. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +3 -3
  335. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +7 -7
  336. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +11 -11
  337. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +57 -51
  338. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +1 -1
  339. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +23 -22
  340. data/lib/phronomy/tool/authorization.rb +77 -0
  341. data/lib/phronomy/tool/base.rb +551 -9
  342. data/lib/phronomy/tool/call_request.rb +40 -0
  343. data/lib/phronomy/{agent/tool_execution/tool_definition_set.rb → tool/definition_set.rb} +7 -8
  344. data/lib/phronomy/tool/operation.rb +88 -0
  345. data/lib/phronomy/tool/schema.rb +214 -0
  346. data/lib/phronomy/tool/settings.rb +31 -0
  347. data/lib/phronomy/tool/tool_error.rb +7 -0
  348. data/lib/phronomy/tool/tool_executor.rb +58 -0
  349. data/lib/phronomy/tools/agent.rb +22 -90
  350. data/lib/phronomy/tools/mcp.rb +21 -14
  351. data/lib/phronomy/tools/vector_search.rb +4 -4
  352. data/lib/phronomy/tracing/automatic.rb +11 -6
  353. data/lib/phronomy/tracing/base.rb +36 -7
  354. data/lib/phronomy/tracing/observation.rb +37 -0
  355. data/lib/phronomy/tracing/open_telemetry_tracer.rb +4 -29
  356. data/lib/phronomy/tracing/settings.rb +36 -0
  357. data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
  358. data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
  359. data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
  360. data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
  361. data/lib/phronomy/vector_store/base.rb +118 -49
  362. data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
  363. data/lib/phronomy/vector_store.rb +2 -17
  364. data/lib/phronomy/version.rb +1 -1
  365. data/lib/phronomy/workflow/completion.rb +11 -0
  366. data/lib/phronomy/workflow/execution/workflow.rb +37 -9
  367. data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
  368. data/lib/phronomy/workflow/execution/workflow_context.rb +2 -2
  369. data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +28 -0
  370. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +77 -8
  371. data/lib/phronomy/workflow/execution/workflow_runner.rb +105 -92
  372. data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
  373. data/lib/phronomy/workflow/execution/workflow_task_execution.rb +153 -0
  374. data/lib/phronomy/workflow/execution/workflow_task_reception.rb +72 -0
  375. data/lib/phronomy/workflow/execution/workflow_task_resume_error.rb +14 -0
  376. data/lib/phronomy/workflow/persistence/state_repository.rb +28 -22
  377. data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
  378. data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +61 -0
  379. data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +158 -0
  380. data/lib/phronomy/workflow/runtime_binding/workflow_task_session.rb +76 -0
  381. data/lib/phronomy/workflow/{execution → runtime_binding}/workflow_terminal_policy.rb +4 -4
  382. data/lib/phronomy.rb +63 -16
  383. data/scripts/api_snapshot.rb +47 -15
  384. data/scripts/check_readme_ruby.rb +24 -29
  385. data/scripts/check_readme_runnable.rb +92 -81
  386. data/sig/_private/phronomy/agent/settings.rbs +19 -0
  387. data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
  388. data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
  389. data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
  390. data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
  391. data/sig/_private/phronomy/tool/settings.rbs +13 -0
  392. data/sig/_private/phronomy/tracing/settings.rbs +15 -0
  393. data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
  394. data/sig/phronomy/agent/admission.rbs +19 -0
  395. data/sig/phronomy/agent/agent_not_found_error.rbs +6 -0
  396. data/sig/phronomy/agent/agent_unloaded_error.rbs +6 -0
  397. data/sig/phronomy/agent/execution_contract.rbs +132 -0
  398. data/sig/phronomy/agent/execution_environment.rbs +20 -0
  399. data/sig/phronomy/agent/store.rbs +73 -0
  400. data/sig/phronomy/agent/stream_callback_error.rbs +8 -0
  401. data/sig/phronomy/agent.rbs +29 -135
  402. data/sig/phronomy/common.rbs +7 -0
  403. data/sig/phronomy/content_store/contracts.rbs +13 -0
  404. data/sig/phronomy/context.rbs +152 -0
  405. data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
  406. data/sig/phronomy/embeddings/base.rbs +23 -0
  407. data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
  408. data/sig/phronomy/engine/control_bindings.rbs +11 -0
  409. data/sig/phronomy/engine/control_protocols.rbs +23 -0
  410. data/sig/phronomy/engine/execution_binding.rbs +6 -0
  411. data/sig/phronomy/engine/execution_receiver.rbs +15 -0
  412. data/sig/phronomy/engine/observability.rbs +13 -0
  413. data/sig/phronomy/execution/async_operation.rbs +7 -0
  414. data/sig/phronomy/execution/blocking.rbs +5 -0
  415. data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
  416. data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
  417. data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
  418. data/sig/phronomy/execution/control_protocols.rbs +18 -0
  419. data/sig/phronomy/execution/errors.rbs +7 -0
  420. data/sig/phronomy/execution/execution.rbs +41 -0
  421. data/sig/phronomy/execution/execution_receiver.rbs +40 -0
  422. data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
  423. data/sig/phronomy/execution/invocation_context.rbs +18 -0
  424. data/sig/phronomy/execution/invocation_controls.rbs +13 -0
  425. data/sig/phronomy/execution/task_result.rbs +29 -0
  426. data/sig/phronomy/extensions.rbs +1 -21
  427. data/sig/phronomy/filter/filter_block_error.rbs +6 -0
  428. data/sig/phronomy/generation/low_confidence_error.rbs +6 -0
  429. data/sig/phronomy/handoff.rbs +10 -4
  430. data/sig/phronomy/integrations.rbs +14 -0
  431. data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
  432. data/sig/phronomy/llm_adapter/base.rbs +14 -0
  433. data/sig/phronomy/llm_adapter/usage.rbs +14 -0
  434. data/sig/phronomy/llm_adapter/values.rbs +43 -0
  435. data/sig/phronomy/llm_context_window.rbs +10 -0
  436. data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
  437. data/sig/phronomy/multi_agent/store.rbs +54 -0
  438. data/sig/phronomy/multi_agent/team_busy_error.rbs +8 -0
  439. data/sig/phronomy/multi_agent/team_not_found_error.rbs +8 -0
  440. data/sig/phronomy/multi_agent.rbs +6 -3
  441. data/sig/phronomy/persistence/errors.rbs +18 -0
  442. data/sig/phronomy/persistence/migration.rbs +13 -0
  443. data/sig/phronomy/persistence/transaction.rbs +19 -0
  444. data/sig/phronomy/persistence.rbs +1 -99
  445. data/sig/phronomy/persistence_composition.rbs +19 -0
  446. data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
  447. data/sig/phronomy/storage/async/async_client.rbs +8 -0
  448. data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
  449. data/sig/phronomy/{storage.rbs → storage/contracts.rbs} +4 -18
  450. data/sig/phronomy/tool.rbs +48 -4
  451. data/sig/phronomy/tracing/observation.rbs +7 -0
  452. data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
  453. data/sig/phronomy/vector_store/base.rbs +23 -0
  454. data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +15 -0
  455. data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
  456. data/sig/phronomy/workflow/store.rbs +8 -0
  457. data/sig/phronomy/workflow.rbs +5 -1
  458. data/sig/phronomy.rbs +4 -49
  459. metadata +365 -117
  460. data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
  461. data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
  462. data/lib/phronomy/agent/concerns/filterable.rb +0 -184
  463. data/lib/phronomy/agent/context/capability/base.rb +0 -548
  464. data/lib/phronomy/agent/context/capability/tool_executor.rb +0 -62
  465. data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
  466. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +0 -36
  467. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +0 -22
  468. data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
  469. data/lib/phronomy/agent/context_policies/default.rb +0 -142
  470. data/lib/phronomy/agent/execution/phase_machine_builder.rb +0 -101
  471. data/lib/phronomy/agent/execution/provider_call_outcome.rb +0 -106
  472. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +0 -15
  473. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +0 -131
  474. data/lib/phronomy/agent/handoff/handoff_request.rb +0 -45
  475. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +0 -7
  476. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +0 -58
  477. data/lib/phronomy/agent/persistence/queries.rb +0 -61
  478. data/lib/phronomy/agent/selection/candidate.rb +0 -53
  479. data/lib/phronomy/agent/selection/constraint.rb +0 -49
  480. data/lib/phronomy/agent/tool_execution/tool_call_intercepted.rb +0 -29
  481. data/lib/phronomy/agent/tool_execution/tool_invocation_session_builder.rb +0 -276
  482. data/lib/phronomy/configuration/configuration.rb +0 -68
  483. data/lib/phronomy/configuration/global_configuration.rb +0 -26
  484. data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
  485. data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
  486. data/lib/phronomy/engine/execution_receiver.rb +0 -65
  487. data/lib/phronomy/engine/runnable.rb +0 -54
  488. data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
  489. data/lib/phronomy/llm_contract/token_usage.rb +0 -85
  490. data/lib/phronomy/multi_agent/persistence/queries.rb +0 -30
  491. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +0 -15
  492. data/lib/phronomy/output_parser/contract/parse_error.rb +0 -7
  493. data/lib/phronomy/persistence/api/persistence.rb +0 -140
  494. data/lib/phronomy/persistence_composition/repositories.rb +0 -77
  495. data/lib/phronomy/recovery/recovery.rb +0 -186
  496. data/lib/phronomy/tool/contract/tool_error.rb +0 -7
  497. data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
  498. data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
  499. data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
  500. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +0 -9
  501. data/sig/phronomy/execution_receiver.rbs +0 -34
  502. data/sig/phronomy/llm_adapter.rbs +0 -11
  503. data/sig/phronomy/runtime.rbs +0 -76
  504. /data/lib/phronomy/agent/{context_assembly/context_importer.rb → context_importer.rb} +0 -0
  505. /data/lib/phronomy/{engine → execution}/backpressure_error.rb +0 -0
  506. /data/lib/phronomy/{engine → execution}/cancellation_error.rb +0 -0
  507. /data/lib/phronomy/{engine → execution}/concurrency/worker_input_restricted.rb +0 -0
  508. /data/lib/phronomy/{engine → execution}/event_loop_reentrancy_error.rb +0 -0
  509. /data/lib/phronomy/{engine → execution}/invalid_async_entry_action_error.rb +0 -0
  510. /data/lib/phronomy/{engine → execution}/invalid_async_transition_action_error.rb +0 -0
  511. /data/lib/phronomy/{engine → execution}/invalid_async_workflow_action_error.rb +0 -0
  512. /data/lib/phronomy/{engine → execution}/pool_shutdown_error.rb +0 -0
  513. /data/lib/phronomy/{engine → execution}/recursion_limit_error.rb +0 -0
  514. /data/lib/phronomy/{engine → execution}/runtime_shutdown_error.rb +0 -0
  515. /data/lib/phronomy/{engine → execution}/runtime_shutdown_reentrancy_error.rb +0 -0
  516. /data/lib/phronomy/{engine → execution}/scheduler_reentrancy_error.rb +0 -0
  517. /data/lib/phronomy/{engine → execution}/timeout_error.rb +0 -0
@@ -0,0 +1,33 @@
1
+ # Migrating to r8 unit 11
2
+
3
+ Apply after core eaff581cb8806c707d47649bb561b70690fa9e57 (unit 10).
4
+ This package changes core only. The unit 6 examples at
5
+ ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
6
+
7
+ No application API changes or database migrations are required. Continue to
8
+ load the library with require "phronomy" and use the existing context_policy
9
+ DSL for explicit policies. The boot composition installs DefaultPolicy through
10
+ that same DSL. Reading an unconfigured internal Base now fails explicitly
11
+ instead of selecting a concrete Policy inside Agent.
12
+
13
+ | Private implementation use | Replacement |
14
+ | --- | --- |
15
+ | Agent::Base concrete Policy fallback | runtime_composition/agent_defaults.rb installs the default |
16
+ | InvocationActions constructs LLMAdapter::AsyncClient | Its captured environment.build_llm_client(adapter: ...) |
17
+ | Agent LLM submission resolves the current global Runtime | EngineEnvironment binds the client to its retained Runtime |
18
+ | AsyncClient constructor | Optional submitter: using existing _ExecutionSubmitter; existing arguments still work |
19
+
20
+ Internal custom ExecutionEnvironment implementations must supply the new client
21
+ capability. It is not a supported application extension API. Clients created
22
+ without an injected submitter preserve their default Runtime behavior; explicit
23
+ pool arguments preserve precedence. Changing the global default Runtime does
24
+ not migrate an existing Agent's resources. Follow the existing stop/drain and
25
+ recreate procedure when replacing running processes.
26
+
27
+ The ZIP contains complete changed files, strict-base application and expected-tree
28
+ verification, a review patch, test evidence and recovery instructions. Run
29
+ --check, --apply and --verify in a new worktree, then --verify after commit.
30
+
31
+ For examples verification, unset BUNDLE_GEMFILE before entering the examples
32
+ checkout and set PHRONOMY_PATH to this core. Inspect and restore only generated
33
+ lockfile/vendor changes; no examples commit is needed.
@@ -0,0 +1,31 @@
1
+ # Migrating to r8 unit 12
2
+
3
+ Apply after core 891ddf62da42e5218fd8f80d5a9ec0ac6b58b81d (unit 11).
4
+ This package changes core only. The unit 6 examples at
5
+ ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
6
+
7
+ Continue to use Orchestrator.subagent and Tools::Agent.from_agent as before.
8
+ No application API or database migration is required. Orchestrator still
9
+ inherits Agent::Base. Its generated Tool is now a direct Tool::Base subclass.
10
+
11
+ | Internal assumption | Current structure |
12
+ | --- | --- |
13
+ | A generated subagent Tool is a Tools::Agent subclass | It implements Tool::Base directly and belongs to MultiAgent |
14
+ | Tools::Agent owns generic asynchronous Tool validation and error handling | Tool::Base supplies private asynchronous operation rules |
15
+ | Generic Tool handling knows Agent recovery errors | Agent-aware callers preserve those outcomes |
16
+
17
+ Code that inspects generated-class ancestry or changes Tools::Agent globally
18
+ to affect Orchestrator-generated Tools relied on the old implementation link.
19
+ Such changes no longer apply to generated subagent operations. Existing Tool
20
+ DSL options on the generated operation retain their semantics. The new private
21
+ helper is not a public asynchronous implementation API.
22
+
23
+ The ZIP includes complete changed files, strict-base application and
24
+ expected-tree verification, a review patch, verification evidence and application
25
+ instructions. Use a new worktree and run --check, --apply and --verify; run
26
+ --verify again after committing. Follow the existing stop/drain procedure when
27
+ replacing running processes. No new cross-version in-flight guarantee is made.
28
+
29
+ For examples verification, unset BUNDLE_GEMFILE and set PHRONOMY_PATH to this
30
+ core. Inspect and restore generated lockfile/vendor changes; no examples commit
31
+ is needed. Live PostgreSQL and provider verification remain environment-specific.
@@ -0,0 +1,36 @@
1
+ # Migrating to r8 unit 13
2
+
3
+ Apply after core 87685e3544901a3b2b2d6e9841a723f8ce05c6f6 (unit 12).
4
+ This package changes core only. Unit 6 examples at
5
+ ed455c52018338f7c5a4c2948ae0d7db131aa090 require no source changes.
6
+
7
+ Workflow.define, invoke, invoke_async, signal, stream and resume retain their
8
+ call signatures and persistence format. No database migration is required.
9
+ Compiled Workflows now retain the execution environment selected at compilation.
10
+ When replacing/resetting the Runtime in a process, drain/stop existing work and
11
+ compile new Workflow objects for the new Runtime. A Workflow whose owner has
12
+ stopped rejects work; it does not implicitly adopt the replacement Runtime.
13
+
14
+ | Internal assumption | Current structure |
15
+ | --- | --- |
16
+ | Runner looks up the global Runtime during each execution step | It retains a private WorkflowExecutionEnvironment |
17
+ | Workflow registry constructs an Engine Event | It supplies an atomic target resolver to the C13 receiver channel |
18
+ | Phase compiler owns callback rules | WorkflowActionRules owns the rules; the binding installs callbacks |
19
+ | Workflow terminal policy belongs to domain execution files | It translates domain outcomes in workflow/runtime_binding |
20
+
21
+ WorkflowPhaseMachineBuilder and WorkflowTerminalPolicy retain their constant
22
+ names but move from workflow/execution to workflow/runtime_binding. They remain
23
+ private; direct internal require paths or private Runner helpers must be updated.
24
+ No application implementation of the environment port is required or supported
25
+ as a new public API. Admission, repository operations and result classification
26
+ remain Workflow-owned.
27
+
28
+ The ZIP contains complete changed files, strict base checks, deletion handling,
29
+ expected-tree verification, a review patch and validation evidence. Apply in a
30
+ new worktree; run --check, --apply and --verify, then --verify after committing.
31
+ For examples, unset BUNDLE_GEMFILE and set PHRONOMY_PATH to the new core. Inspect
32
+ and restore generated lockfile/vendor changes. No examples commit is needed.
33
+
34
+ This change does not introduce durable child execution, cross-version in-flight
35
+ compatibility or external-side-effect rollback. Keep the existing stop/drain and
36
+ recovery procedures when replacing running processes.
@@ -0,0 +1,31 @@
1
+ # r8 unit 14 migration
2
+
3
+ Apply to unit13 core commit `cf659de00b9adc2641e1c68014d756e761ccc8e1` using
4
+ the package applier in a clean checkout. Only core changes; examples source
5
+ remains at unit6 commit `ed455c52018338f7c5a4c2948ae0d7db131aa090`.
6
+
7
+ Public Agent resolution and Workflow APIs are unchanged. There is no data
8
+ migration, persistence format change or new application configuration.
9
+
10
+ Private consumers must replace the removed `Phronomy::Recovery` namespace:
11
+
12
+ | Former member | New private owner |
13
+ | --- | --- |
14
+ | Classification, dispositions, resolution outcomes, missing-material sentinel | `Phronomy::Agent::RecoveryRules` |
15
+ | Subject normalization/identity and resolution material validation | `Phronomy::Agent::RecoveryRules` |
16
+ | Revision and snapshot comparison, value normalization and record access | `Phronomy::Persistence::SnapshotComparison` |
17
+
18
+ The existing public `Phronomy::ExecutionRehydrationRequiredError` keeps its name
19
+ and superclass; its file moves to `agent/api/execution_rehydration_required_error.rb`.
20
+
21
+ The old internal file `lib/phronomy/recovery/recovery.rb` is removed.
22
+ Ordinary `require "phronomy"` loads both replacements. Direct loading of
23
+ internal files remains unsupported; do not treat these private modules as new
24
+ application extension APIs. Existing `Persistence::SaveOutcome` is unchanged.
25
+
26
+ Use the same process stop/drain and deployment procedure as unit13. This unit
27
+ adds no in-flight version interoperability or external side-effect rollback
28
+ guarantee. Retain the unit13 checkout for rollback; revert the applied commit
29
+ if necessary. Package README contains apply, validation and commit instructions.
30
+
31
+ Workflow durable children (F01) are deferred and are not included in this unit.
@@ -0,0 +1,31 @@
1
+ # r8 unit15 migration
2
+
3
+ ## Application impact
4
+
5
+ No public API, data migration or configuration changes are required.
6
+ GeneratorVerifier continues to accept draft/review Agent classes and optional
7
+ result parser callables, with the same JSON parser defaults and fallback values.
8
+ Each supplied Agent is created once and reused, retaining its conversation.
9
+
10
+ Custom Agent classes should implement the public Agent protocol: constructor
11
+ `on_event:`, `invoke_async` returning TaskResult, and approval notifications through
12
+ the constructor-bound listener. Terminal results are observed on the returned
13
+ TaskResult. A test double that emits `:done` but leaves its TaskResult pending is
14
+ not a complete implementation of that protocol and must settle its result.
15
+
16
+ The private `__invoke_async_with_event_sink` method is removed. It was not a
17
+ supported application API. Do not substitute `invoke_async(..., on_event:)`;
18
+ per-invocation listener arguments remain rejected. Register the listener at Agent
19
+ construction and observe each call's result near the call site.
20
+
21
+ `GeneratorVerifier::DefaultParser` and the private AgentOperation are framework
22
+ composition details. Applications continue to use `draft_result_parser:` and
23
+ `review_result_parser:` for custom parsing.
24
+
25
+ ## Operational scope
26
+
27
+ The package applies only to core on top of unit14. Existing unit6 examples need
28
+ verification against the new core but no source migration. Restart using the
29
+ existing stop/drain procedure. Rollback is a revert of the unit15 commit; it does
30
+ not require rewriting stored data. In-flight cross-version behavior is not a new
31
+ guarantee of this refactor.
@@ -0,0 +1,26 @@
1
+ # r8 unit16 migration
2
+
3
+ No application API or persisted-data migration is required.
4
+
5
+ This core-only update moves explicit-cancellation registration lifetime into the
6
+ existing internal `Phronomy::Concurrency::ResultSubscriptions` operation. Team
7
+ and OffloadPool use `explicit_cancellation` and `close`, rather than removing
8
+ CancellationToken callbacks through reflection.
9
+
10
+ `CancellationToken#on_cancel` remains public and returns `self`. Its private
11
+ callback-removal method remains private. The new internal operation is not an
12
+ application configuration option or a public subscription API.
13
+
14
+ Existing cancellation and deadline behavior is preserved. Deadline expiry alone
15
+ does not become a new Team cancellation notification. OffloadPool's existing
16
+ deadline promotion and non-interrupting worker completion behavior remain.
17
+ An already-dispatched cancellation callback can still run after subscription
18
+ cleanup; this refactor does not add a stronger delivery guarantee.
19
+
20
+ Tool cooperative execution and custom `call_async` implementations are unchanged.
21
+ The standard offloaded Tool route benefits from the OffloadPool update without
22
+ requiring Tool-specific registration code. Examples sources are unchanged.
23
+
24
+ Apply from unit15 commit `9aebef9217383cebb7fa3ec8b2d17b5763cd3c5e` in a new
25
+ `refactor/r8-unit16` worktree using the package's checked applier. Follow the
26
+ existing process shutdown/drain procedure when replacing running code.
@@ -0,0 +1,28 @@
1
+ # r8 unit17 migration
2
+
3
+ This core-only update requires no application or stored-data migration.
4
+ Continue using Phronomy.configure and the existing per-instance/per-invocation
5
+ options. Public names, defaults, policy validation, nil semantics, and explicit
6
+ option priority remain unchanged.
7
+
8
+ Agent and Workflow read their own option values instead of application
9
+ Configuration. MultiAgent uses its optional configured Store provider. Logging
10
+ uses RuntimeSettings. Authorization pool sizing moves into the execution
11
+ connection while Agent retains approval and timeout decisions.
12
+
13
+ There is no settings-change notification or automatic in-flight update. Existing
14
+ read timing is preserved, including scoped configuration restoration and reset.
15
+ Do not capture an internal settings object as a permanent replacement for the
16
+ current accessor, or depend on Configuration's private instance variables.
17
+
18
+ Private Agent ExecutionEnvironment implementations used by internal integrations
19
+ or tests must implement submit_authorization(timeout:, cancellation_token:, &block).
20
+ The default Engine connection submits the same authorization work with the same
21
+ pool name, resource defaults, overload behavior, and owning Runtime. Ordinary
22
+ Tool implementations and application code require no changes. Tests should set
23
+ configuration through its writers rather than intercepting an old facade getter.
24
+
25
+ Apply from unit16 commit `fb551e1a1a8334b2547ecad126dd9c152c1b0f8c` in a new
26
+ `refactor/r8-unit17` worktree using the package's checked applier. Follow the
27
+ existing shutdown/drain procedure when replacing running code. Examples remain
28
+ on their unit6 sources and are verified against this core through PHRONOMY_PATH.
@@ -0,0 +1,29 @@
1
+ # R8 unit18 migration
2
+
3
+ Apply to core at unit17 commit `26792401144118f03025952aa9ec849fb16b577f`.
4
+ No examples source changes, public API updates, schema migrations or data rewrites
5
+ are required. Existing cancellation records remain valid.
6
+
7
+ Exact-execution resume with a cancelled token now records the request in the
8
+ existing Agent ledger before continuing recovery/waiting. A recording failure is
9
+ returned to the caller. Unresolved children continue to require factual resolution
10
+ and the parent remains active; cancellation receipt does not claim completion.
11
+
12
+ Cancellation metadata on the execution and MultiAgent extension is a snapshot of
13
+ its last save. If cancellation is recorded after that save, the independent Agent
14
+ ledger preserves intent until the next recovery/change reflects it. Use the
15
+ existing Agent cancellation observation instead of assuming every stored
16
+ snapshot is immediately updated.
17
+
18
+ Keep the existing stop/drain procedure when replacing running processes. This
19
+ package does not establish new compatibility guarantees for workers already
20
+ running code from another version. Reverting this source change needs no data
21
+ rollback, but reintroduces the cancellation-loss race.
22
+
23
+ ## Delivery correction package
24
+
25
+ The unit18 cancellation-delivery correction applies on top of
26
+ `a89f42e3805fb548bf9587c49e1ab226efd174db`. It removes the gap between the
27
+ recording and notification decisions in `ExactExecution` delivery. The existing
28
+ preparation/delivery recheck, cancellation ledger and error behavior remain.
29
+ There are no additional API, schema or examples changes.
@@ -0,0 +1,28 @@
1
+ # R8 unit19 migration
2
+
3
+ Apply to core at unit18 delivery-correction commit
4
+ `a6f370d34e90ca274ec45a6b69ad1db9cb003707`.
5
+ No examples source change, data migration or public invocation API change is
6
+ required. Engine-private shutdown operations and their RBS declarations change.
7
+
8
+ Runtime shutdown now reports incomplete cleanup when workers remain alive. Check
9
+ cleanup_complete? before declaring resources released. reset_runtime! continues
10
+ to reject replacement after incomplete cleanup. Do not bypass that guard or
11
+ assume a cancelled TaskResult means its synchronous worker has stopped.
12
+
13
+ The existing Runtime stop-phase deadline, computed from cancel_grace with its
14
+ existing minimum grace, now also bounds pool joins. It is shared across EventLoop
15
+ and all pools; the previous additional 30 seconds per worker no longer applies
16
+ to Runtime shutdown. timeout still controls the preceding drain phase. Choose
17
+ grace appropriate to existing work, and configure native I/O timeouts where
18
+ needed. No Thread#raise or hard worker termination is added.
19
+
20
+ Shutdown remains terminal and returns its cached result on subsequent calls,
21
+ including an incomplete result. This change does not add retry or resume of the
22
+ shutdown procedure. Pool requests racing past the closed resource registry are
23
+ rejected with PoolShutdownError; new calls rejected earlier by Runtime retain
24
+ RuntimeShutdownError.
25
+
26
+ Use the existing controlled process-replacement procedure. Reverting the source
27
+ change needs no data rollback, but restores the resource leak and false-completion
28
+ risks. Metrics.snapshot behavior is unchanged in this unit (E03 is deferred).
@@ -0,0 +1,24 @@
1
+ # R8 unit20 migration
2
+
3
+ Apply to unit19 core commit `07b78c90ef6072f66fecb04ea6891eda50493546`.
4
+ No examples source change or data migration is required.
5
+
6
+ Metrics.snapshot, Diagnostics.snapshot and Diagnostics.dump keep their arguments,
7
+ metric keys, numeric values and output format. They no longer initialize execution
8
+ resources and remain usable while the default Runtime is stopping or stopped.
9
+
10
+ Before resource initialization, the corresponding values are zero. In particular,
11
+ offload_pool_size is zero until the default pool exists. Previously a snapshot
12
+ created the pool and reported its configured capacity. Do not use monitoring as
13
+ an implicit warmup. Normal execution still initializes the resources it needs.
14
+
15
+ For an existing pool, offload_pool_size remains its configured capacity after
16
+ shutdown; use the shutdown result to assess cleanup, not this metric. Retained
17
+ counters remain readable until default Runtime reset. After reset, observations
18
+ return zero until new resources are initialized. Named pools are not aggregated,
19
+ and simultaneous consistency across independently sampled counters is not added.
20
+
21
+ Unit19 stopping deadlines, completion judgment and cached-result behavior remain
22
+ unchanged. No public invocation API or persistence format changes. Reverting this
23
+ unit needs no data rollback but restores observation-triggered initialization and
24
+ shutdown-time diagnostic errors.
@@ -0,0 +1,28 @@
1
+ # r8 unit21 migration
2
+
3
+ This core-only responsibility refactor requires no application or stored-data
4
+ migration. Continue using Phronomy.configure with tool_result_max_size, tracer
5
+ and trace_pii, and the existing per-Tool max_result_size option. Public defaults,
6
+ nil semantics, read timing, truncation and redaction behavior remain unchanged.
7
+ Application-configured filter order and repetition remain unchanged too.
8
+
9
+ Tool and Tracing now obtain their settings through their own internal value
10
+ containers. Context::Assembly obtains its default tracer from Tracing while
11
+ retaining explicit injection and constructor-time selection. Composition still
12
+ selects concrete defaults and supplies current values; no manual per-operation
13
+ injection or settings-change subscription is required.
14
+
15
+ Internal tests or unsupported integrations constructing RuntimeSettings must
16
+ stop passing tracer: to its constructor or reading tracer, trace_pii and
17
+ tool_result_max_size from it. Ordinary application code should use the unchanged
18
+ public Configuration accessors. Its private instance variables and the new
19
+ domain settings containers are not an application extension API.
20
+
21
+ Apply from unit20 commit `bda5da03da5a4da33041953cf0eebaa32de7bb81` in a new
22
+ `refactor/r8-unit21` worktree using the package's checked applier. Verify the
23
+ expected tree before and after committing. Follow the existing shutdown/drain
24
+ procedure when replacing running code. Examples remain on their unit6 sources
25
+ and are verified against this core through PHRONOMY_PATH.
26
+
27
+ No data rollback is needed. Reverting this commit restores the earlier settings
28
+ ownership; it does not remove the unit19/20 Engine corrections.
@@ -0,0 +1,29 @@
1
+ # r8 unit22 migration
2
+
3
+ No application source or stored-data migration is required. Apply this core-only
4
+ package on unit21 commit `4525e71ca808acac9eb0302a59c32f00478a7782` and restart
5
+ using the application's existing drain/shutdown procedure.
6
+
7
+ - MCP public construction, execution, close, schema, authorization and result
8
+ formatting APIs are unchanged.
9
+ - A completed MCP call no longer retains a cancellation callback on a shared
10
+ caller token. A callback already taken by concurrent cancel! may still finish.
11
+ - Logical timeout does not end the SDK invocation's cancellation bridge. The
12
+ registration is released when that invocation exits.
13
+ - If Runtime rejects transport cleanup because it has stopped, the MCP caller
14
+ performs the existing synchronous close fallback and still receives the MCP
15
+ cancellation outcome. This can include the transport's normal close latency.
16
+ - Warning logging uses the same configured logger through neutral settings,
17
+ with stderr fallback when no logger is configured.
18
+
19
+ Execution, Engine and Contract source are unchanged. There are no new threads,
20
+ configuration options, timers or notification services. The existing MCP
21
+ cleanup pool remains in use while Runtime accepts work.
22
+
23
+ Custom tests that expected cancellation to reach an already-completed MCP call
24
+ should instead cancel while the SDK call is active and verify that completed
25
+ calls release their registrations. The SDK cancellation bridge helper is
26
+ private; its new subscriptions keyword is not a public application API.
27
+
28
+ Examples retain their unit6 source. Verify them against this core checkout using
29
+ PHRONOMY_PATH and restore only verification-generated lockfiles/artifacts.
@@ -0,0 +1,20 @@
1
+ # r8 unit23 migration
2
+
3
+ This is a core-only responsibility refactor on applied unit22.
4
+
5
+ - `Tools::Agent.from_agent`, synchronous `execute`, asynchronous `call_async`
6
+ and the public `Agent.run_once` API retain their signatures and behavior.
7
+ - Agent Tool calls still create a fresh Agent and ephemeral store. Configured
8
+ application stores do not replace this per-call store.
9
+ - `Testing::Eval::Scorer::LlmJudge` retains its constructor and scoring API.
10
+ Configure `llm_adapter` through the existing application configuration API.
11
+ - LlmJudge reads the default adapter for each score, after preparing its Request.
12
+ Existing scoped configuration and reset behavior are retained.
13
+ - The client factory is an internal boot binding. Applications do not need to
14
+ register it or adopt a new factory API.
15
+ - No Contract, Execution, Engine, RBS, data schema or stored-record migration is
16
+ required. Examples require verification only, with no source changes.
17
+
18
+ Use the package README to check the exact base commit, apply complete files,
19
+ verify the resulting tree, run the validation commands and commit the result.
20
+ Normal application loading remains `require "phronomy"`.
@@ -0,0 +1,67 @@
1
+ # r8 unit 4 migration
2
+
3
+ Update core and examples together. This is a refactoring-branch breaking change;
4
+ there are no compatibility aliases or automatic old-record loaders.
5
+
6
+ | Unit 3 | Unit 4 |
7
+ |---|---|
8
+ | `Agent::Handoff`, `Agent::HandoffPolicy` | `MultiAgent::Handoff`, `MultiAgent::HandoffPolicy` |
9
+ | `stores.team`, `config.team_store` | `stores.multi_agent`, `config.multi_agent_store` |
10
+ | HandoffRunner infers an Agent store | `HandoffRunner.new(main_agent:, handoffs:, persistence: stores.multi_agent)` |
11
+ | Orchestrator receives only Agent persistence | `Orchestrator.create(persistence: stores.agent, coordination_store: stores.multi_agent)`; pass both on `load` |
12
+ | Internal ExactExecution/metadata access by coordination | Agent reserved start, resume, cancellation and observation operations |
13
+ | AgentExecution / HandoffState envelope `0.1` | Envelope `0.2`; explicit offline conversion required |
14
+ | `coordination`, `multi_agent_coordination_ref`, Handoff result fields | immutable `reservation`, versioned `execution_extension`, `transfer_receipt` |
15
+
16
+ Construct one `PersistenceComposition.build(backend:)` and use its domain stores.
17
+ Ordinary Agents continue to use `persistence: stores.agent`. For custom
18
+ participants, follow `ExecutionChange`'s RBS contract and the
19
+ [transaction sequence](../architecture/r8-unit4.md). Do not serialize participant
20
+ objects, callbacks or live Agent references.
21
+
22
+ ## Offline SQL conversion
23
+
24
+ Stop all writers before exporting, including background workers and other
25
+ processes. Keep the old database unchanged. Run commands from example 30 (SQLite)
26
+ or 31 (PostgreSQL), with `PHRONOMY_PATH` pointing to the unit 4 core. The source DB
27
+ must have the unit 3 schema. The destination must be a separate empty database.
28
+
29
+ ```sh
30
+ export SOURCE_DATABASE_URL='sqlite3:/absolute/path/old.sqlite3'
31
+ export DESTINATION_DATABASE_URL='sqlite3:/absolute/path/new.sqlite3'
32
+ bundle exec ruby ../scripts/migrate_unit4.rb export source.json --quiescent
33
+ bundle exec ruby ../scripts/migrate_unit4.rb convert source.json converted.json --quiescent
34
+ bundle exec ruby ../scripts/migrate_unit4.rb import converted.json --quiescent
35
+ bundle exec ruby ../scripts/migrate_unit4.rb verify converted.json --quiescent
36
+ ```
37
+
38
+ Use the corresponding PostgreSQL URLs with example 31. The importer creates the
39
+ new destination schema, including retention/cancellation tables, refuses populated
40
+ tables, and commits all resources together. It preserves record IDs, physical and
41
+ logical revisions, stream positions, result/error content, transfer provenance,
42
+ knowledge order and unresolved work. A content digest, reference, owner, revision
43
+ or format mismatch aborts conversion. A checksum binds the converted resource set
44
+ to its validation. Do not edit converted JSON manually.
45
+
46
+ Verification establishes a separate connection pool and compares the complete
47
+ exported destination with the converted snapshot. Before switching application
48
+ configuration, load representative Agents with their current definitions and
49
+ participant wiring, read completed results and resume only continuations whose
50
+ external outcomes are known. Unknown external operations remain unresolved; the
51
+ migration neither retries them nor declares them complete. Keep both exports and
52
+ the old DB until that operational validation is complete. Database cutover is
53
+ explicit and is never performed by the migration command.
54
+
55
+ For non-SQL backends, `Unit4Migration.convert(snapshot, quiescent: true)` is the
56
+ pure conversion boundary. Implement offline export/import of the documented
57
+ `phronomy.snapshot/1` resources using the backend's own driver. No live-code
58
+ fallback is supplied.
59
+
60
+ ## Retention lifecycle
61
+
62
+ After all results in a conversation have been consumed, call
63
+ `runner.forget_history!` (or `stores.multi_agent.forget_handoff(main_id)`) before
64
+ purging retained participants. For completed durable subagent history use
65
+ `stores.multi_agent.forget_subagents(agent_id:, execution_id:)`. Active or
66
+ unresolved work rejects history deletion. These operations release their own
67
+ holds; they do not remove another conversation's references.
@@ -0,0 +1,75 @@
1
+ # r8 unit 5 API migration
2
+
3
+ Apply core and examples together. No saved Agent, MultiAgent or Workflow record
4
+ format changes in this unit. Old constants and forwarding aliases are removed.
5
+
6
+ | Previous API | Current API |
7
+ | --- | --- |
8
+ | `Phronomy::VectorStore::Embeddings::*` | `Phronomy::Embeddings::*` |
9
+ | `Phronomy::VectorStore::Loader::*` | `Phronomy::Documents::Loader::*` |
10
+ | `Phronomy::VectorStore::Splitter::*` | `Phronomy::Documents::Splitter::*` |
11
+
12
+ VectorStore callers continue using `add`, `search`, `remove`, `clear` and `size`.
13
+ Custom backends now override protected `perform_add`, `perform_search`,
14
+ `perform_remove`, `perform_clear`, `perform_size`, and optionally
15
+ `embedding_dimension`. The common Base performs input/result validation and
16
+ returns `self` for add/remove/clear; the return value from these three hooks is
17
+ ignored. See `sig/phronomy/vector_store/base.rbs` for exact arguments. RBS models
18
+ the non-public hooks as private because it cannot express Ruby protected visibility.
19
+
20
+ Custom embedding providers implement the protected hook, not the public template:
21
+
22
+ ```ruby
23
+ class KeywordEmbeddings < Phronomy::Embeddings::Base
24
+ protected
25
+
26
+ def perform_embed(text, cancellation_token = nil)
27
+ # Common input/result validation and the initial cancellation checkpoint
28
+ # are inherited. Long-running implementations may check the signal again.
29
+ [text.scan(/refund/i).length.to_f, text.scan(/shipping/i).length.to_f]
30
+ end
31
+ end
32
+
33
+ provider = KeywordEmbeddings.new
34
+ vector = provider.embed("refund")
35
+ task = Phronomy::Embeddings::AsyncClient.new(adapter: provider).embed_async("shipping")
36
+ result = task.wait_result
37
+ ```
38
+
39
+ Embedding input must be a String, including an optional empty string; output must
40
+ be a non-empty Array of finite real numbers. Provider output is copied to a Float
41
+ array. An empty or malformed vector raises `Embeddings::InvalidResultError`.
42
+ RubyLLM provider failures now raise `Embeddings::TransportError`; inspect `cause`
43
+ for provider-specific details. Application exceptions are unchanged.
44
+
45
+ Vector ids must be Strings and metadata must be a Hash. Numeric strings, NaN,
46
+ infinity and complex components are rejected before backend I/O. Zero-dimensional
47
+ vectors still work in InMemory. `k` accepts positive Integers or decimal strings,
48
+ including `"08"`; Float truncation, hexadecimal/octal interpretation, whitespace
49
+ and arbitrary `to_int` coercions are not part of the contract. Results must satisfy
50
+ the public shape, score ordering and limit. Invalid backend results raise
51
+ `VectorStore::InvalidResultError`; they are never retried automatically.
52
+
53
+ Update custom backend tests to exercise inherited public operations. Do not
54
+ silence malformed results, return a fake zero count on transport failure, or add
55
+ an old-name alias to bypass the migration. Real Pgvector and RedisSearch deployments
56
+ must run their actual-service conformance tests before rollout.
57
+
58
+ The revised unit 5 candidate also tightens concrete backend response decoding.
59
+ RedisSearch expects RESP2; a missing whole search reply, malformed field pairs,
60
+ invalid counts or non-numeric distances now fail with `InvalidResultError` rather
61
+ than becoming an empty result, zero count or similarity 1. Document contents that
62
+ Redis explicitly reports as null during expiration/update are still omitted.
63
+ The total match count may exceed the returned page; these valid cases are tested.
64
+ RESP3 is not introduced by this update.
65
+
66
+ For Pgvector, a NULL metadata column remains `{}`, while an empty string, invalid
67
+ JSON, or JSON that is not an object now fails. An already-decoded Hash and a JSON
68
+ object remain accepted. Redis missing/null metadata likewise remains `{}`.
69
+ Pgvector rejects malformed scores and ids; integer database ids are still mapped
70
+ to String. JSON parser errors are retained as `cause`. Connection errors remain
71
+ unchanged and are not retried.
72
+
73
+ Check pre-existing metadata for invalid JSON or non-object values before rollout;
74
+ do not silently replace corrupt values with `{}` to make verification pass.
75
+ These parsing rules are implemented by the respective backend, not by Base.
@@ -0,0 +1,109 @@
1
+ # r8 unit 6 migration
2
+
3
+ Apply core and examples together on the applied unit 5 baseline. There are no
4
+ compatibility aliases. Update custom adapters and code rescuing LLM failures.
5
+
6
+ | Previous API | Current API |
7
+ | --- | --- |
8
+ | `Phronomy::TokenUsage` | `Phronomy::LLMAdapter::TokenUsage` |
9
+ | `Phronomy::TransportError` | `Phronomy::LLMAdapter::TransportError` |
10
+ | `Phronomy::RateLimitError` | `Phronomy::LLMAdapter::RateLimitError` |
11
+ | `Phronomy::AuthenticationError` | `Phronomy::LLMAdapter::AuthenticationError` |
12
+ | `Phronomy::ContextLengthError` | `Phronomy::LLMAdapter::ContextLengthError` |
13
+ | Adapter `build_chat`, `configure_chat`, `message`, `tool_call` | Backend-owned private translation; removed from the extension SPI |
14
+ | Adapter `complete(chat, message, config:)` / `stream(...)` | Inherited `complete(request, cancellation_token:)` / `stream(...)` |
15
+ | SDK-shaped recovery provider result | `LLMAdapter::Response` or `Response#to_h` |
16
+
17
+ Implement protected hooks, leaving public validation/cancellation templates intact:
18
+
19
+ ```ruby
20
+ class EchoBackend < Phronomy::LLMAdapter::Base
21
+ protected
22
+
23
+ def perform_complete(request, cancellation_token:)
24
+ Phronomy::LLMAdapter::Response.new(content: request.message || "continued")
25
+ end
26
+
27
+ def perform_stream(request, cancellation_token:)
28
+ result = perform_complete(request, cancellation_token: cancellation_token)
29
+ yield Phronomy::LLMAdapter::StreamChunk.new(content: result.content)
30
+ result
31
+ end
32
+ end
33
+ Phronomy.configure { |config| config.llm_adapter = EchoBackend.new }
34
+ ```
35
+
36
+ Request contains JSON model_config, optional system/new message, immutable
37
+ Message history and inert Tool definition Hashes. `identity` and local
38
+ `input_budget` have defaults. Backend hooks return Response; stream yields
39
+ StreamChunk values. Tool requests are `Tool::CallRequest(id:, name:, arguments:,
40
+ metadata:)` values in an ordered array, with unique nonempty IDs. They never
41
+ contain executable Tools or approval decisions. Return assistant responses only.
42
+ Response/Message content is text, structured JSON or nil. Unknown token counts
43
+ are nil; explicit zero is zero. TokenUsage no longer provides SDK `from_tokens`.
44
+
45
+ Model/provider are nonempty Strings or nil, temperature a finite number or nil,
46
+ max_output_tokens a positive Integer or nil, and instruction-cache/model-existence
47
+ flags booleans or nil. The default RubyLLM backend still owns provider-specific
48
+ options and error translation. Existing provider/application errors are not
49
+ silently swallowed or converted into success. Custom synchronous hooks must
50
+ check cancellation during their own long operations where they can cooperate.
51
+
52
+ ## Tool schemas and approval
53
+
54
+ Tool::Base owns `parameter`/`param`, `parameters`/`params`, declaration inheritance,
55
+ name/description, provider options, `validate_arguments`, `call`, and `call_async`.
56
+ It is not a RubyLLM::Tool. Incidental inherited SDK APIs such as approval_resolver,
57
+ split_result and SDK result/content classes are not part of the new Tool API.
58
+ Keep Agent approval policies on the Agent/Tool authorization contract.
59
+
60
+ `parameters` accepts an explicit object schema or Schematist DSL (the DSL retains
61
+ its syntax without loading RubyLLM). JSON Schema 2020-12 is the supported dialect,
62
+ implicit when `$schema` is absent. Root type must be object. Supported constraints
63
+ include required/extra properties, nested objects/arrays, enum/const, numbers,
64
+ strings/formats and combinators. Unknown keywords/formats, alternate dialects,
65
+ custom vocabularies, `$id`/anchors and external refs fail at declaration time.
66
+ Local `#` / `#/...` references are resolved at construction. `strict` is a provider
67
+ annotation, not a substitute for required/additionalProperties constraints.
68
+ Defaults are annotations and are not injected into arguments.
69
+
70
+ Legacy optional `param` declarations continue to accept explicit nil and now
71
+ advertise a nullable type (and nullable enum). A legacy optional nil is normalized
72
+ to omission before approval/execution, preserving Ruby keyword defaults. An
73
+ absent optional key is not injected. Explicit schemas accept null only when their own constraints allow it.
74
+
75
+ Every declaration path validates before execution. `:raise` raises ToolError;
76
+ `:return_error` returns the existing schema-error text; `:coerce` converts explicit
77
+ primitive property/item types and then validates every constraint. It does not
78
+ guess a branch or cast through references/combinators. Fractional values are not
79
+ truncated to integers. Validation snapshots input containers; it does not mutate
80
+ the caller's arguments. Top-level keys become keyword symbols. Extra keys with
81
+ no declared/inferred parameters are rejected rather than passed to execute.
82
+
83
+ Approval receives the validated/coerced snapshot. Execution reuses those values
84
+ and validates against the same published schema. `on_error` does not turn schema
85
+ errors into successful execution. Unqualified legacy array declarations now
86
+ advertise unconstrained JSON items, matching their actual validation rule; use
87
+ an explicit items schema to restrict them.
88
+
89
+ ## Stored and in-flight executions
90
+
91
+ Storage SPI and SQL schemas are unchanged. New Tool batch metadata additionally
92
+ records `validated_arguments`, separately from the unchanged raw request fields.
93
+ Agent authorization projects and compares that exact snapshot (including explicit
94
+ null in explicit schemas). Older snapshots without this field use the historical
95
+ raw-argument/optional-nil-omission rule. Existing journal message boundaries,
96
+ Tool call identities and recorded usage remain readable. Legacy top-level
97
+ thought_signature is decoded into opaque CallRequest metadata and rendered by
98
+ the backend. Old SDK usage field spellings remain accepted by SavedContextReader.
99
+ No stored records are silently rewritten and no automatic migration is run.
100
+
101
+ Saved Tool definitions are compared exactly. Removing SDK-generated annotations,
102
+ correctly advertising nested required/extra-key rules or array item rules can
103
+ change the definition even when application source is unchanged. Finish or
104
+ explicitly resolve in-flight unit 5 executions on their original version before
105
+ upgrading. Quiescent Agent history remains readable. If a saved in-flight Tool
106
+ definition differs, recovery rejects it; do not remove that comparison or modify
107
+ historical manifests to force continuation. Saved invalid model configuration
108
+ also needs resolution on the original version. No new cross-version in-flight
109
+ compatibility guarantee is made.