phronomy 0.26.0 → 0.27.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 (304) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +4 -0
  4. data/VERIFY.sh +27 -27
  5. data/benchmark/bench_agent_invoke.rb +26 -22
  6. data/benchmark/bench_context_assembler.rb +4 -5
  7. data/docs/architecture/agent-chat-and-state-ownership.md +147 -0
  8. data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
  9. data/docs/architecture/agent-context.md +4 -2
  10. data/docs/architecture/agent-transition-ownership.md +89 -0
  11. data/docs/architecture/before-llm-input.md +6 -0
  12. data/docs/architecture/context-management.md +30 -0
  13. data/docs/architecture/context-preparation-steps.md +90 -0
  14. data/docs/architecture/entry-action-and-team-wording.md +72 -0
  15. data/docs/architecture/execution-metadata-and-values.md +80 -0
  16. data/docs/architecture/generator-verifier-ownership.md +111 -0
  17. data/docs/architecture/multi-agent-handoff.md +8 -2
  18. data/docs/architecture/persistence-refactoring-plan.md +50 -0
  19. data/docs/architecture/persistence.md +27 -4
  20. data/docs/architecture/refactoring-closure.md +334 -0
  21. data/docs/architecture/remaining-refactoring-plan.md +374 -0
  22. data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
  23. data/docs/architecture/tool-schema-recording-gap.md +50 -0
  24. data/docs/architecture/tracing.md +1 -1
  25. data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
  26. data/docs/architecture.md +209 -0
  27. data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
  28. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
  29. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
  30. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
  31. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +5 -0
  32. data/docs/decisions/031-durable-multi-agent-coordination.md +5 -0
  33. data/docs/decisions/032-storage-backend-composition.md +80 -0
  34. data/docs/decisions/033-domain-persistence-ownership.md +79 -0
  35. data/docs/decisions/034-handoff-runner-coordination-ownership.md +76 -0
  36. data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
  37. data/docs/decisions/036-context-contract-ownership.md +86 -0
  38. data/docs/decisions/037-common-definition-ownership.md +62 -0
  39. data/docs/decisions/038-responsibility-based-source-layout.md +131 -0
  40. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +74 -0
  41. data/docs/decisions/040-configuration-default-composition.md +94 -0
  42. data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
  43. data/docs/decisions/042-feature-owned-execution-state.md +106 -0
  44. data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
  45. data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
  46. data/docs/decisions/045-worker-input-restriction-ownership.md +100 -0
  47. data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
  48. data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
  49. data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
  50. data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
  51. data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
  52. data/docs/decisions/051-execution-outcome-worker-ownership.md +151 -0
  53. data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
  54. data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
  55. data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
  56. data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
  57. data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
  58. data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
  59. data/docs/decisions/058-neutral-storage-primitives.md +78 -0
  60. data/docs/decisions/README.md +35 -6
  61. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
  62. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
  63. data/docs/features.md +9 -3
  64. data/docs/getting-started.md +4 -4
  65. data/docs/migrations/0.15.md +5 -0
  66. data/docs/migrations/durable-semantic-coordination-v2.md +6 -0
  67. data/docs/migrations/handoff-runner-multi-agent.md +35 -0
  68. data/docs/migrations/neutral-storage-spi.md +43 -0
  69. data/docs/migrations/parallel-tool-chat-removal.md +49 -0
  70. data/docs/migrations/shared-state-multi-agent.md +44 -0
  71. data/docs/migrations/storage-backend-composition.md +117 -0
  72. data/docs/migrations/storage-transaction-boundaries.md +74 -0
  73. data/docs/persistence-backends.md +162 -204
  74. data/docs/runtime-and-concurrency.md +117 -32
  75. data/lib/phronomy/agent/api/agent.rb +17 -0
  76. data/lib/phronomy/agent/async_event_api.rb +2 -2
  77. data/lib/phronomy/agent/base.rb +51 -241
  78. data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
  79. data/lib/phronomy/agent/context/capability/base.rb +67 -26
  80. data/lib/phronomy/agent/context/capability/tool_executor.rb +62 -0
  81. data/lib/phronomy/agent/{context_assembler.rb → context_assembly/context_assembler.rb} +143 -88
  82. data/lib/phronomy/agent/{context_importer.rb → context_assembly/context_importer.rb} +2 -2
  83. data/lib/phronomy/agent/{ruby_llm_materializer.rb → context_assembly/ruby_llm_materializer.rb} +4 -7
  84. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +36 -0
  85. data/lib/phronomy/agent/context_assembly/saved_context_reader.rb +53 -0
  86. data/lib/phronomy/agent/context_assembly/state_writer.rb +165 -0
  87. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +22 -0
  88. data/lib/phronomy/agent/{context_plan.rb → context_contract/context_plan.rb} +1 -1
  89. data/lib/phronomy/agent/{context_policy_input.rb → context_contract/context_policy_input.rb} +6 -6
  90. data/lib/phronomy/agent/{llm_input_build_context.rb → context_contract/llm_input_build_context.rb} +1 -1
  91. data/lib/phronomy/agent/{llm_input_manifest.rb → context_contract/llm_input_manifest.rb} +20 -20
  92. data/lib/phronomy/agent/{llm_input_patch.rb → context_contract/llm_input_patch.rb} +2 -2
  93. data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
  94. data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +8 -13
  95. data/lib/phronomy/agent/{agent_invocation_session_builder.rb → execution/agent_invocation_session_builder.rb} +19 -95
  96. data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
  97. data/lib/phronomy/agent/execution/dispatch_preparation.rb +305 -0
  98. data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +9 -10
  99. data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +2 -3
  100. data/lib/phronomy/agent/execution/execution_coordinator.rb +1925 -0
  101. data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
  102. data/lib/phronomy/agent/execution/execution_metadata.rb +53 -0
  103. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +344 -0
  104. data/lib/phronomy/agent/execution/execution_registry.rb +459 -0
  105. data/lib/phronomy/agent/execution/execution_session_runner.rb +118 -0
  106. data/lib/phronomy/agent/execution/initial_preparation.rb +421 -0
  107. data/lib/phronomy/agent/execution/invocation_transitions.rb +86 -0
  108. data/lib/phronomy/agent/{phase_machine_builder.rb → execution/phase_machine_builder.rb} +20 -71
  109. data/lib/phronomy/agent/{provider_call_outcome.rb → execution/provider_call_outcome.rb} +9 -9
  110. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
  111. data/lib/phronomy/agent/{handoff_context.rb → handoff/handoff_context.rb} +2 -2
  112. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +15 -0
  113. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +131 -0
  114. data/lib/phronomy/agent/{handoff_state.rb → handoff/handoff_state.rb} +1 -1
  115. data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
  116. data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
  117. data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
  118. data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
  119. data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
  120. data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -10
  121. data/lib/phronomy/{agent_already_exists_error.rb → agent/lifecycle_contract/agent_already_exists_error.rb} +2 -0
  122. data/lib/phronomy/{agent_busy_error.rb → agent/lifecycle_contract/agent_busy_error.rb} +2 -0
  123. data/lib/phronomy/{agent_purged_error.rb → agent/lifecycle_contract/agent_purged_error.rb} +2 -0
  124. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +7 -0
  125. data/lib/phronomy/{stream_callback_error.rb → agent/lifecycle_contract/stream_callback_error.rb} +2 -0
  126. data/lib/phronomy/agent/persistence/agent_repository.rb +61 -0
  127. data/lib/phronomy/agent/persistence/codec.rb +358 -0
  128. data/lib/phronomy/agent/persistence/execution_repository.rb +108 -0
  129. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +58 -0
  130. data/lib/phronomy/agent/persistence/journal_repository.rb +54 -0
  131. data/lib/phronomy/agent/persistence/queries.rb +61 -0
  132. data/lib/phronomy/agent/persistence/storage_schema.rb +24 -0
  133. data/lib/phronomy/agent/persistence/watermark.rb +27 -0
  134. data/lib/phronomy/agent/recovery/invocation_restorer.rb +132 -0
  135. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +21 -45
  136. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +32 -37
  137. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +37 -40
  138. data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +6 -10
  139. data/lib/phronomy/agent/recovery/recovery_support.rb +227 -0
  140. data/lib/phronomy/agent/selection/candidate.rb +1 -1
  141. data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
  142. data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
  143. data/lib/phronomy/agent/tool_execution/tool_binding.rb +90 -0
  144. data/lib/phronomy/agent/{tool_call_intercepted.rb → tool_execution/tool_call_intercepted.rb} +2 -2
  145. data/lib/phronomy/agent/{tool_definition_set.rb → tool_execution/tool_definition_set.rb} +9 -4
  146. data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +69 -34
  147. data/lib/phronomy/common/configuration_error.rb +7 -0
  148. data/lib/phronomy/common/error.rb +5 -0
  149. data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
  150. data/lib/phronomy/common/values/serializable.rb +32 -0
  151. data/lib/phronomy/{configuration.rb → configuration/configuration.rb} +14 -5
  152. data/lib/phronomy/configuration/global_configuration.rb +26 -0
  153. data/lib/phronomy/content_store/storage_schema.rb +11 -0
  154. data/lib/phronomy/content_store/stored_contents.rb +43 -0
  155. data/lib/phronomy/engine/backpressure_error.rb +7 -0
  156. data/lib/phronomy/{blocking.rb → engine/blocking.rb} +1 -1
  157. data/lib/phronomy/engine/cancellation_error.rb +7 -0
  158. data/lib/phronomy/engine/concurrency/cancellation_token.rb +4 -0
  159. data/lib/phronomy/engine/concurrency/offload_pool.rb +4 -0
  160. data/lib/phronomy/engine/concurrency/operation_binding.rb +1 -1
  161. data/lib/phronomy/engine/concurrency/worker_input_restricted.rb +14 -0
  162. data/lib/phronomy/engine/event_loop.rb +158 -624
  163. data/lib/phronomy/engine/event_loop_reentrancy_error.rb +8 -0
  164. data/lib/phronomy/{execution.rb → engine/execution.rb} +0 -7
  165. data/lib/phronomy/{execution_cancellation_error.rb → engine/execution_cancellation_error.rb} +2 -0
  166. data/lib/phronomy/engine/execution_receiver.rb +65 -0
  167. data/lib/phronomy/{execution_timeout_error.rb → engine/execution_timeout_error.rb} +2 -0
  168. data/lib/phronomy/engine/fsm_protocol.rb +14 -0
  169. data/lib/phronomy/engine/fsm_session.rb +35 -28
  170. data/lib/phronomy/{invalid_async_entry_action_error.rb → engine/invalid_async_entry_action_error.rb} +2 -0
  171. data/lib/phronomy/{invalid_async_transition_action_error.rb → engine/invalid_async_transition_action_error.rb} +2 -0
  172. data/lib/phronomy/{invalid_async_workflow_action_error.rb → engine/invalid_async_workflow_action_error.rb} +2 -0
  173. data/lib/phronomy/engine/pool_shutdown_error.rb +7 -0
  174. data/lib/phronomy/engine/recursion_limit_error.rb +7 -0
  175. data/lib/phronomy/engine/runtime.rb +80 -84
  176. data/lib/phronomy/engine/runtime_shutdown_error.rb +7 -0
  177. data/lib/phronomy/engine/runtime_shutdown_reentrancy_error.rb +7 -0
  178. data/lib/phronomy/engine/scheduler_reentrancy_error.rb +9 -0
  179. data/lib/phronomy/engine/task_result.rb +4 -0
  180. data/lib/phronomy/engine/timeout_error.rb +7 -0
  181. data/lib/phronomy/filter/contract/filter_block_error.rb +14 -0
  182. data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
  183. data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
  184. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
  185. data/lib/phronomy/generation/generator_verifier.rb +118 -0
  186. data/lib/phronomy/generation/low_confidence_error.rb +14 -0
  187. data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
  188. data/lib/phronomy/llm_contract/authentication_error.rb +7 -0
  189. data/lib/phronomy/{context_budget_exceeded_error.rb → llm_contract/context_budget_exceeded_error.rb} +2 -0
  190. data/lib/phronomy/llm_contract/context_length_error.rb +7 -0
  191. data/lib/phronomy/llm_contract/rate_limit_error.rb +7 -0
  192. data/lib/phronomy/{token_usage.rb → llm_contract/token_usage.rb} +2 -2
  193. data/lib/phronomy/llm_contract/transport_error.rb +7 -0
  194. data/lib/phronomy/multi_agent/admission_registry.rb +22 -2
  195. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +5 -5
  196. data/lib/phronomy/{agent → multi_agent}/handoff_runner.rb +18 -17
  197. data/lib/phronomy/multi_agent/orchestrator.rb +2 -2
  198. data/lib/phronomy/multi_agent/persistence/codec.rb +55 -0
  199. data/lib/phronomy/multi_agent/persistence/queries.rb +30 -0
  200. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +108 -0
  201. data/lib/phronomy/multi_agent/persistence/team_repository.rb +61 -0
  202. data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
  203. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +15 -0
  204. data/lib/phronomy/multi_agent/team_coordinator.rb +21 -18
  205. data/lib/phronomy/multi_agent/team_execution.rb +1 -1
  206. data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +14 -4
  207. data/lib/phronomy/multi_agent/team_root.rb +1 -1
  208. data/lib/phronomy/output_parser/contract/parse_error.rb +7 -0
  209. data/lib/phronomy/persistence/api/persistence.rb +140 -0
  210. data/lib/phronomy/persistence/migration/initial_format_migration.rb +19 -19
  211. data/lib/phronomy/persistence_composition/repositories.rb +77 -0
  212. data/lib/phronomy/persistence_composition/storage_schema.rb +24 -0
  213. data/lib/phronomy/{execution_rehydration_required_error.rb → recovery/execution_rehydration_required_error.rb} +2 -0
  214. data/lib/phronomy/{recovery.rb → recovery/recovery.rb} +1 -1
  215. data/lib/phronomy/runtime_composition/agent_defaults.rb +7 -0
  216. data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
  217. data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
  218. data/lib/phronomy/storage/backend.rb +101 -0
  219. data/lib/phronomy/storage/backends/in_memory.rb +157 -0
  220. data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
  221. data/lib/phronomy/storage/blobs.rb +31 -0
  222. data/lib/phronomy/storage/condition.rb +25 -0
  223. data/lib/phronomy/storage/condition_failed_error.rb +16 -0
  224. data/lib/phronomy/storage/conflict_error.rb +9 -0
  225. data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
  226. data/lib/phronomy/storage/entry.rb +33 -0
  227. data/lib/phronomy/storage/guard_ref.rb +13 -0
  228. data/lib/phronomy/storage/not_found_error.rb +9 -0
  229. data/lib/phronomy/storage/record_codec.rb +177 -0
  230. data/lib/phronomy/storage/records.rb +61 -0
  231. data/lib/phronomy/storage/resource.rb +126 -0
  232. data/lib/phronomy/storage/scope.rb +25 -0
  233. data/lib/phronomy/storage/serialization_error.rb +9 -0
  234. data/lib/phronomy/storage/streams.rb +44 -0
  235. data/lib/phronomy/storage/transaction_error.rb +10 -0
  236. data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
  237. data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
  238. data/lib/phronomy/storage/validation.rb +53 -0
  239. data/lib/phronomy/storage/view.rb +131 -0
  240. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
  241. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +4 -4
  242. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +10 -7
  243. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +2 -2
  244. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +6 -6
  245. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +6 -6
  246. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +8 -8
  247. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
  248. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +123 -0
  249. data/lib/phronomy/testing/persistence_contract.rb +4 -0
  250. data/lib/phronomy/tool/contract/tool_error.rb +7 -0
  251. data/lib/phronomy/tools/agent.rb +1 -1
  252. data/lib/phronomy/version.rb +1 -1
  253. data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +8 -6
  254. data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +4 -0
  255. data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
  256. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +188 -0
  257. data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +122 -71
  258. data/lib/phronomy/workflow/execution/workflow_terminal_policy.rb +40 -0
  259. data/lib/phronomy/workflow/persistence/codec.rb +153 -0
  260. data/lib/phronomy/workflow/persistence/state_repository.rb +57 -0
  261. data/lib/phronomy/workflow/phase_machine_builder.rb +2 -2
  262. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +9 -0
  263. data/lib/phronomy.rb +52 -94
  264. data/scripts/api_snapshot.rb +1 -1
  265. data/scripts/storage_spi_snapshot.rb +36 -0
  266. data/sig/phronomy/agent.rbs +0 -1
  267. data/sig/phronomy/execution_receiver.rbs +34 -0
  268. data/sig/phronomy/handoff.rbs +4 -2
  269. data/sig/phronomy/multi_agent.rbs +18 -0
  270. data/sig/phronomy/persistence.rbs +7 -91
  271. data/sig/phronomy/storage.rbs +174 -0
  272. data/sig/phronomy/tool.rbs +10 -1
  273. metadata +230 -99
  274. data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
  275. data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
  276. data/lib/phronomy/agent/recovery_support.rb +0 -504
  277. data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
  278. data/lib/phronomy/agent/tool_executor.rb +0 -55
  279. data/lib/phronomy/generator_verifier.rb +0 -369
  280. data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
  281. data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
  282. data/lib/phronomy/persistence/durable_codec.rb +0 -706
  283. data/lib/phronomy/persistence/in_memory.rb +0 -690
  284. data/lib/phronomy/persistence/repository_facades.rb +0 -535
  285. data/lib/phronomy/persistence.rb +0 -276
  286. data/lib/phronomy/ruby_llm_patches.rb +0 -24
  287. data/lib/phronomy/workflow_recovery.rb +0 -123
  288. /data/lib/phronomy/agent/{context_candidate_resolver.rb → context_assembly/context_candidate_resolver.rb} +0 -0
  289. /data/lib/phronomy/agent/{context_policy_input_builder.rb → context_assembly/context_policy_input_builder.rb} +0 -0
  290. /data/lib/phronomy/agent/{context_plan_validator.rb → context_contract/context_plan_validator.rb} +0 -0
  291. /data/lib/phronomy/agent/{context_policy.rb → context_contract/context_policy.rb} +0 -0
  292. /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
  293. /data/lib/phronomy/agent/{handoff.rb → handoff/handoff.rb} +0 -0
  294. /data/lib/phronomy/agent/{handoff_capability_factory.rb → handoff/handoff_capability_factory.rb} +0 -0
  295. /data/lib/phronomy/agent/{handoff_policy.rb → handoff/handoff_policy.rb} +0 -0
  296. /data/lib/phronomy/agent/{handoff_projection.rb → handoff/handoff_projection.rb} +0 -0
  297. /data/lib/phronomy/agent/{handoff_request.rb → handoff/handoff_request.rb} +0 -0
  298. /data/lib/phronomy/agent/{tool_invocation_session_builder.rb → tool_execution/tool_invocation_session_builder.rb} +0 -0
  299. /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
  300. /data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +0 -0
  301. /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
  302. /data/lib/phronomy/{invocation_context.rb → engine/invocation_context.rb} +0 -0
  303. /data/lib/phronomy/{metrics.rb → engine/metrics.rb} +0 -0
  304. /data/lib/phronomy/{runnable.rb → engine/runnable.rb} +0 -0
@@ -0,0 +1,60 @@
1
+ # ADR-055: Settle Terminal Observer Failures
2
+
3
+ ## Status
4
+
5
+ Accepted on the architecture refactoring branch, 2026-09-23.
6
+ Clarifies terminal observer failure ordering in
7
+ [026-workflow-runtime-admission-and-durable-terminal-barrier](026-workflow-runtime-admission-and-durable-terminal-barrier.md).
8
+ It does not move Workflow terminal policy out of FSMSession; that remains W2b.
9
+
10
+ ## Problem
11
+
12
+ FSMSession marked itself done before delivering a pending stable-state observer
13
+ notification. If that observer raised at a wait state or a declared terminal
14
+ state, the existing error handler saw done and returned without an error event.
15
+ The synchronous stream caller remained blocked and Workflow admission stayed
16
+ owned. Durable executions could already have saved their terminal snapshot.
17
+
18
+ The existing observer-exception test covered an automatic transition's ordinary
19
+ stable notification, before terminalization. It did not cover the deferred
20
+ terminal notification. Six real-runtime observations on both pre-Refactor-31 and
21
+ applied Refactor-31 source reproduce four affected cases and two unaffected
22
+ automatic-transition controls. This is not a regression introduced by Refactor 31.
23
+
24
+ ## Decision
25
+
26
+ Keep the existing terminal lifecycle selection, invoke the pending stable
27
+ observer, and set done only after the observer returns successfully. If it
28
+ raises, the existing start/handle/request error boundary emits the ordinary
29
+ error event with the original exception. EventLoop retires the session and the
30
+ existing Runner completion path releases admission before failing the caller.
31
+
32
+ Preserve successful notification-before-terminal-event ordering. All transitions
33
+ remain on EventLoop. Do not introduce a new class, callback retry, extra save,
34
+ Task settlement path, or direct admission mutation from the observer.
35
+
36
+ ## Durable meaning and limits
37
+
38
+ A durable terminal observer runs only after the session accepts a known-success
39
+ save result. Observer failure therefore means notification failed; it does not
40
+ mean the save failed, and must not erase, roll back, or repeat the saved record.
41
+ The caller receives the original observer exception. Applications must not
42
+ assume that every raised stream exception proves non-commit, nor replay external
43
+ effects automatically. This adds no exactly-once or crash-atomic notification
44
+ guarantee; existing F1/F4/X0 limits remain.
45
+
46
+ Known save failure and unresolved save uncertainty are unchanged. In particular,
47
+ the outcome-unknown path still retires the session without falsely settling the
48
+ Workflow Task or releasing its recovery-required admission.
49
+
50
+ ## Verification
51
+
52
+ Add public stream regressions for wait/declared-terminal boundaries, each with
53
+ and without persistence. Require the same exception object, one notification
54
+ on EventLoop, caller completion, session retirement and admission release.
55
+ For durable cases, also require the existing snapshot and revision 1 to remain.
56
+ Keep test cleanup bounded so these tests can demonstrate failure on old source.
57
+
58
+ Run the shared FSMSession/Agent/Tool tests, Workflow admission and F1 tests, full
59
+ and integration suites, API/RBS/style, examples and real SQLite. Keep W2b policy
60
+ extraction in a later package after application verification of this fix.
@@ -0,0 +1,87 @@
1
+ # ADR-056: Workflow-Owned Terminal Policy
2
+
3
+ ## Status
4
+
5
+ Accepted on the architecture refactoring branch, 2026-09-23.
6
+ Amends the implementation ownership in
7
+ [ADR-026](026-workflow-runtime-admission-and-durable-terminal-barrier.md).
8
+ Preserves the ordering and failure semantics clarified by
9
+ [ADR-055](055-terminal-observer-failure-settlement.md).
10
+
11
+ ## Context
12
+
13
+ FSMSession is used by WorkflowRunner, AgentInvocationSessionBuilder and
14
+ ToolInvocationSessionBuilder. It belongs to Engine, but it directly recognized
15
+ Workflow persistence events and interpreted success, known failure and unknown
16
+ save outcomes. Moving the entire session would couple Agent and Tool to Workflow.
17
+ Runner already owns the one terminal save and F1 reconciliation (ADR-054), and
18
+ WorkflowExecutionRegistry already owns admission and owner tokens (ADR-042).
19
+
20
+ ## Decision
21
+
22
+ WorkflowRunner injects a WorkflowTerminalPolicy only for durable execution.
23
+ Ephemeral Workflow, Agent and Tool sessions keep their immediate terminal path.
24
+ The policy holds the persistence callback, not live session state or admission.
25
+
26
+ The private session protocol is:
27
+
28
+ - `start(terminal_type:, context:, event_sink:)` begins the barrier on EventLoop.
29
+ Its return value does not authorize completion. Results use the bound sink.
30
+ - `handles?(event)` recognizes a policy event, including an early event that
31
+ must be discarded by the session before any terminal request.
32
+ - `decision_for(event)` interprets an accepted event and returns the immutable
33
+ `FSMProtocol::TerminalDecision(action:, error:)` value.
34
+
35
+ WorkflowTerminalPolicy maps success to `complete`, known failure to `fail` with
36
+ its original error or the existing fallback error, and outcome unknown to
37
+ `retire` with its diagnostic error. Invalid Workflow outcomes remain errors.
38
+ FSMSession knows these generic actions, not the Workflow event or outcome values.
39
+ An unsupported action fails through the existing session error path.
40
+
41
+ FSMSession alone owns the pending terminal type, stable-notification flag and
42
+ acceptance state. It enters `awaiting_terminal` before starting the policy,
43
+ ignores ordinary events during that wait, ignores early policy events, and
44
+ accepts at most one terminal decision. The policy must not maintain a second
45
+ pending lifecycle or mutate the session from a worker.
46
+
47
+ `complete` delivers any deferred stable notification before marking done and
48
+ posting the terminal event. `fail` uses the existing failure path. `retire`
49
+ marks the session retired and uses EventLoop's existing recovery-required
50
+ management route without settling a result. Runner persistence/F1 code,
51
+ Registry ownership and EventLoop retirement/shutdown code remain unchanged.
52
+
53
+ ## Uncertainty and shutdown
54
+
55
+ Retirement for an unknown save result removes the concrete routing session and
56
+ retains recovery-required admission. It does not complete or fail the caller.
57
+ The old sink cannot target a subsequent incarnation. Normal Runtime shutdown
58
+ clears Registry ownership and terminates the dispatcher, but does not synthesize
59
+ a Workflow result: the unresolved caller remains pending. Unexpected dispatcher
60
+ failure has its separate existing waiter cleanup. These are preserved behaviors,
61
+ not a new guarantee of automatic recovery or a stronger F1/F4/X0 contract.
62
+
63
+ ## Compatibility and non-goals
64
+
65
+ `terminal_barrier:` is replaced by private `terminal_policy:` with no alias.
66
+ The internal lifecycle names change to `awaiting_terminal` and `retired`.
67
+ Neither constructor injection nor these states are a new public plugin API.
68
+ Without an injected policy, Engine no longer reserves a Workflow-only event
69
+ name. Workflow's producer emits that event only for its durable execution path.
70
+ Session identity, EventSink correlation, public Workflow/Agent/Tool APIs,
71
+ Workflow result types, durable records and Storage SPI are unchanged.
72
+
73
+ Do not move snapshot persistence into the policy, settle caller Tasks there,
74
+ rename outcome strings while leaving interpretation in Engine, introduce a
75
+ subclass/prepend override, or duplicate admission. A small new policy and value
76
+ type clarify ownership; reducing the total line count is not the objective.
77
+
78
+ ## Verification
79
+
80
+ The generic session contract uses a non-Workflow event and policy, exercising
81
+ early/ordinary/duplicate events, completion, failure, retirement, submission
82
+ error, malformed decisions and the immediate default path. Workflow tests cover
83
+ invalid outcomes and the existing missing-error fallback through Runner wiring.
84
+ Real Runtime tests cover F1 pre-state, conflicting/unreadable readback, retained
85
+ admission and normal shutdown, stale sinks across incarnations, and submission
86
+ rejection. Existing delayed-save, halted-stream, observer-failure, Agent/Tool and
87
+ F1 tests remain acceptance gates; rejected result delivery must not retry save.
@@ -0,0 +1,73 @@
1
+ # ADR-057: Storage update constraints and explicit transaction boundaries
2
+
3
+ ## Status
4
+
5
+ Accepted for implementation in Refactor 34 (Storage S2a).
6
+
7
+
8
+ The raw fixed-repository/error portions are amended by [ADR-058](058-neutral-storage-primitives.md). Domain ownership and applicable transaction/uncertainty decisions remain in force.
9
+
10
+ ## Context
11
+
12
+ The existing eight-repository SPI had three concrete behavioral differences.
13
+ InMemory allowed an inactive Agent execution to become active while another
14
+ execution for that Agent was active. SQL rejected that update. SQL Journal
15
+ append serialized each record immediately before inserting it; catching an
16
+ invalid later record inside the outer transaction could commit earlier rows
17
+ without advancing the head. Explicit nested InMemory transactions restored an
18
+ inner snapshot, whereas ActiveRecord's default nesting joined the outer scope.
19
+
20
+ ## Decision
21
+
22
+ Keep the existing SPI and data formats while closing these differences.
23
+
24
+ 1. InMemory checks active-owner uniqueness on Agent execution updates under the
25
+ same Monitor as revision validation and writes. Exclude the updated identity.
26
+ Report `Storage::ActiveExecutionConflictError` and leave record and revision
27
+ unchanged on rejection. Team terminal execution reactivation remains forbidden.
28
+ 2. Both SQL Journal adapters serialize the complete batch and normalize the
29
+ expected position before any writes. Preserve ID checks, lock order, CAS,
30
+ return values and transaction-bound connection access.
31
+ 3. Explicit `Backend#transaction` / `Persistence#transaction` nesting on the same
32
+ backend and synchronous execution context uses savepoint semantics. Roll back
33
+ a failed inner scope and re-raise the same exception. The outer scope may catch
34
+ it and continue. Inner success is not an independent commit: outer failure
35
+ rolls back both. SQL uses `requires_new: true` on the same checked-out
36
+ connection. InMemory retains its reentrant Monitor and snapshots.
37
+
38
+ The SQL wrappers also re-raise `ActiveRecord::Rollback` after ActiveRecord rolls
39
+ back and consumes it. The Storage API does not use an exception as a successful
40
+ return value. Repository operations on a bound view still join that scope; this
41
+ change does not introduce per-operation savepoints or separate connections.
42
+
43
+ ## Compatibility and migration
44
+
45
+ This intentionally changes SQL behavior. If an application catches an inner
46
+ failure, writes from that failed inner block will no longer remain in the outer
47
+ transaction. Catch outside the explicit inner block and re-read any conditions
48
+ needed to continue. Catching a database failure inside the same transaction view
49
+ and continuing is not a portable recovery contract; propagate it or isolate the
50
+ operation in an explicit inner transaction before executing it.
51
+
52
+ `ActiveRecord::Rollback` now propagates from the Storage/Persistence boundary.
53
+ Callers relying on ActiveRecord's silent rollback must catch it outside that
54
+ boundary. Backend authors should run the public Persistence contract suite;
55
+ method signatures and required capability keys are unchanged.
56
+
57
+ No schema, record type/version, payload, content identity or public facade
58
+ changes are required. Unknown commit outcomes remain backend/database failures;
59
+ this decision does not add exactly-once behavior or retry external effects.
60
+
61
+ ## Verification and remaining work
62
+
63
+ Shared tests cover rejected update immutability, nonconflicting active updates,
64
+ invalid later Journal records, retrying the same record IDs, inner-only rollback,
65
+ exception identity, continued outer writes, normal results and outer rollback.
66
+ Both raw Backend and domain Persistence transaction entry points are exercised.
67
+ SQL-specific tests cover `ActiveRecord::Rollback` propagation.
68
+
69
+ The new neutral Records/Streams/Blobs SPI, failed-view lifecycle and explicit
70
+ non-local block-exit handling (`return` / `break` / `throw`) belong to S2b.
71
+ Do not use non-local exits as portable commit controls. PostgreSQL live-server
72
+ conformance and concurrency tests remain a required integration gate; source
73
+ parity or tests with a non-PostgreSQL connection do not satisfy that gate.
@@ -0,0 +1,78 @@
1
+ # ADR-058: Neutral Storage primitives and scoped transactions
2
+
3
+ ## Status
4
+
5
+ Accepted. Applied and verified in Refactor 35 (Storage S2b/S2c), core
6
+ `ebd99623f94c8b2db2d74355bfa39f01550778a0` and examples
7
+ `68a0bbd0e354b9e00bbfed728ad2b769b389ed8a`.
8
+
9
+ ## Context
10
+
11
+ S1 inventoried 37 raw methods across eight required domain slots. Moving their
12
+ classes did not remove Agent watermark or active-owner policy from shared
13
+ storage. S2a fixed concrete transaction and update differences first. S2b now
14
+ changes the extension contract while preserving domain APIs and durable data.
15
+
16
+ ## Decision
17
+
18
+ 1. Replace the eight-slot Backend/Repositories SPI with declared Resources and
19
+ Records, Streams, Blobs accessed through View. Storage has no domain codecs,
20
+ active-execution interpretation, content digest or Agent watermark method.
21
+ 2. Keep schemas, encoding, initial revisions, active-state interpretation and
22
+ metadata validation in their features. Composition gathers declarations and
23
+ builds domain wrappers. Team/Workflow schema loader roots do not load runtime.
24
+ 3. Use named equality indexes, conditional unique constraints, immutable metadata,
25
+ revision CAS, stream head CAS and a closed guarded-condition set. Parent guards
26
+ precede child locks. Required parent absence is uniformly NotFoundError.
27
+ 4. Keep one transaction domain, scoped views, same-connection savepoints and root
28
+ handle routing. Reject expired/cross-thread views and failed physical scopes.
29
+ Reject non-local block exits with TransactionError and rollback. A successful
30
+ optional read returning nil is not a failed physical operation.
31
+ 5. Report neutral UniqueConstraintError(resource ID, constraint name) and
32
+ ConditionFailedError(condition). Only owning domain repositories map exact
33
+ active constraints to AgentBusyError. Remove the old domain-named error alias.
34
+ 6. Share neutral SQL operations in examples/shared/storage, with explicit dialect
35
+ differences and separate domain/table composition. Keep all existing tables,
36
+ indexes, envelope formats, payloads, IDs and content bytes. Nullable unique-key
37
+ fields are distinct, matching SQL default uniqueness semantics.
38
+
39
+ ## Supersession scope
40
+
41
+ This amends ADR-032's raw eight-slot contract, ADR-033's remaining fixed raw
42
+ boundary, ADR-043's domain-named raw exception and ADR-057's old-SPI-only limit.
43
+ Their domain ownership, composition, savepoint and uncertainty decisions remain.
44
+ No historical artifact is silently reinterpreted as a current SPI specification.
45
+
46
+ ## Public contract and migration
47
+
48
+ Persistence's constructor, in_memory, eight accessors, result queries and public
49
+ capabilities remain. Backend SPI 2 is intentionally breaking; legacy duck-typed
50
+ backends fail capability validation. There is no compatibility facade or alias.
51
+ See the [contract](../persistence-backends.md), [migration guide](../migrations/neutral-storage-spi.md),
52
+ RBS and explicit SPI 2 snapshot. Ordinary product API snapshots remain separate.
53
+
54
+ ## Validation and remaining gates
55
+
56
+ Shared conformance tests cover opaque data, CAS, named constraints, parents,
57
+ Unicode cursor ordering, streams, binary blobs, all-resource rollback, nested
58
+ savepoints, view lifetime, thread confinement and non-local exits. Domain tests
59
+ retain F0/F1/F4 behavior and X0 limitations. SQLite old/new/old round-trip checks
60
+ cover all eight resources and unchanged schema. The applied SPI 2 pair passed
61
+ [PostgreSQL 17.11 CI](https://github.com/Raizo-TCS/phronomy-examples/actions/runs/35827495677)
62
+ on Ruby 3.2/3.3/3.4, with 119 examples per version and fresh-pool reload. Both
63
+ checkout SHAs were verified. Earlier SPI CI was not used as substitute evidence.
64
+ No stronger commit certainty, distributed Workflow admission or external-effect
65
+ retry is introduced.
66
+
67
+ ## S3 internal responsibility clarification
68
+
69
+ Refactor 36 keeps all public SPI 2 signatures and Resource identity rules.
70
+ Resource normalizes a schema object or resource ID before GuardRef/Condition
71
+ construction; the cooperation method is `@api private`, not a new backend
72
+ extension point. Generic Validation handles scalar validation and copying and
73
+ must not depend on Resource. View still enforces catalog membership and exact
74
+ schema identity. This removes the internal Resource/Validation cycle without
75
+ changing a public name, transaction, stored record or physical backend.
76
+
77
+ See the [closure review](../architecture/refactoring-closure.md) for retained
78
+ placements and the separate distribution application gate.
@@ -62,7 +62,7 @@ resolved explicitly.
62
62
  | [`011-delegate-transport-policy-to-adapters`](011-delegate-transport-policy-to-adapters.md) | Accepted | Yes | Legacy duplicate numeric prefix; use the full canonical key. |
63
63
  | [`012-canonical-execution-log-and-context-policy`](012-canonical-execution-log-and-context-policy.md) | Accepted | Yes | Current Journal / Manifest / Context authority. |
64
64
  | [`013-journal-backed-knowledge-as-context-candidates`](013-journal-backed-knowledge-as-context-candidates.md) | Accepted | Yes | Current persistent Knowledge authority. |
65
- | [`014-unified-persistence-durable-state`](014-unified-persistence-durable-state.md) | Accepted | Yes | Durable-backend and live-owner/no-reload intent remains current; live Agent execution mutation is refined by ADR-024, same-process Agent identity/admission ownership by ADR-025, and same-process Workflow admission/terminal-barrier ordering by ADR-026. Workflow identity terminology is superseded by ADR-020, generic `InvocationContext` / Agent correlation semantics by ADR-021, and concrete FSMSession/Agent-Tool routing identity by ADR-023. |
65
+ | [`014-unified-persistence-durable-state`](014-unified-persistence-durable-state.md) | Accepted | Yes | Durable-backend and live-owner/no-reload intent remains current; [032-storage-backend-composition](032-storage-backend-composition.md) refines storage contract ownership and replaces the backend inheritance SPI; live Agent execution mutation is refined by ADR-024, same-process Agent identity/admission ownership by ADR-025, and same-process Workflow admission/terminal-barrier ordering by ADR-026. Workflow identity terminology is superseded by ADR-020, generic `InvocationContext` / Agent correlation semantics by ADR-021, and concrete FSMSession/Agent-Tool routing identity by ADR-023. |
66
66
  | [`015-tool-public-facade-and-rbs-boundary`](015-tool-public-facade-and-rbs-boundary.md) | Accepted | Yes | Current Tool façade / extension-SPI / RBS boundary. |
67
67
  | [`016-semantic-multi-agent-handoff`](016-semantic-multi-agent-handoff.md) | Superseded | No | Superseded by [ADR-030](030-agent-handoff-domain-and-durable-responsibility.md), including Agent-domain ownership and exact Target recovery. |
68
68
  | [`017-design-authority-and-adr-governance`](017-design-authority-and-adr-governance.md) | Accepted | Yes | Repository-wide architecture authority and ADR governance. |
@@ -72,14 +72,43 @@ resolved explicitly.
72
72
  | [`021-generic-agent-invocation-identity-removal`](021-generic-agent-invocation-identity-removal.md) | Accepted | Yes | Removes generic Agent/InvocationContext identity and canonical Journal `correlation_id`; CG-02 is closed, with targeted legacy durable-key read compatibility and no eager rewrite. |
73
73
  | [`022-agent-execution-parent-identity-and-runtime-routing-boundary`](022-agent-execution-parent-identity-and-runtime-routing-boundary.md) | Accepted | Yes | Canonicalizes Agent-owned Tool/approval logical parent as `execution_id`; CG-03a is reconciled, ADR-023 supplies incarnation routing, and ADR-024 supplies EventLoop result/live-state authority. |
74
74
  | [`023-fsm-session-incarnation-identity-and-routing`](023-fsm-session-incarnation-identity-and-routing.md) | Accepted | Yes | FSMSession-owned incarnation identity, session-local Agent/Tool/Multi-Agent routing, and stale-target drop remain current. Its transitional Workflow identity-reservation/admission bridge is superseded by ADR-026; Agent result authority is completed by ADR-024. |
75
- | [`024-event-loop-single-writer-agent-runtime`](024-event-loop-single-writer-agent-runtime.md) | Accepted | Yes | EventLoop is the single writer of Phronomy-managed live Agent execution state; removes Activation/ActivationRegistry and defines operation-specific Offload result application with current FSM + semantic-ID authority. |
76
- | [`025-process-local-agent-ownership-and-runtime-admission`](025-process-local-agent-ownership-and-runtime-admission.md) | Accepted | Yes | One mutable live Agent owner per `agent_id` per Runtime; EventLoop is the primary same-process top-level admission authority while Persistence admission remains durable defense. |
77
- | [`026-workflow-runtime-admission-and-durable-terminal-barrier`](026-workflow-runtime-admission-and-durable-terminal-barrier.md) | Accepted | Yes | EventLoop-owned opaque Workflow admission owner, admission-before-hydration ordering, and FSMSession-integrated durable terminal save barrier with fail-closed uncertain outcomes. |
75
+ | [`024-event-loop-single-writer-agent-runtime`](024-event-loop-single-writer-agent-runtime.md) | Amended | Yes | EventLoop is the single writer of Phronomy-managed live Agent execution state; removes Activation/ActivationRegistry and defines operation-specific Offload result application with current FSM + semantic-ID authority. Implementation ownership/delivery amended by [042-feature-owned-execution-state](042-feature-owned-execution-state.md). |
76
+ | [`025-process-local-agent-ownership-and-runtime-admission`](025-process-local-agent-ownership-and-runtime-admission.md) | Amended | Yes | One mutable live Agent owner per `agent_id` per Runtime; EventLoop is the primary same-process top-level admission authority while Persistence admission remains durable defense. ADR-041 moves registry implementation to Agent while retaining Runtime-scoped lifetime. Implementation ownership/delivery amended by [042-feature-owned-execution-state](042-feature-owned-execution-state.md). |
77
+ | [`026-workflow-runtime-admission-and-durable-terminal-barrier`](026-workflow-runtime-admission-and-durable-terminal-barrier.md) | Amended | Yes | EventLoop-owned opaque Workflow admission owner, admission-before-hydration ordering, and FSMSession-integrated durable terminal save barrier with fail-closed uncertain outcomes. Implementation ownership/delivery amended by [042-feature-owned-execution-state](042-feature-owned-execution-state.md). |
78
78
  | [`027-llm-adapter-provider-boundary`](027-llm-adapter-provider-boundary.md) | Accepted | Yes | Phronomy-owned Provider-call extension boundary; RubyLLM is the default adapter/integration while current input materialization remains RubyLLM-specific. |
79
79
  | [`028-preparing-recovery-replay-contract`](028-preparing-recovery-replay-contract.md) | Accepted | Yes | Adds replay-safe same-`execution_id` recovery for durably admitted Agent `:preparing` executions when replayability is durably established; unsupported Runtime-only dependencies fail closed. |
80
80
  | [`029-semantic-completion-and-application-effect-boundary`](029-semantic-completion-and-application-effect-boundary.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
81
- | [`030-agent-handoff-domain-and-durable-responsibility`](030-agent-handoff-domain-and-durable-responsibility.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
82
- | [`031-durable-multi-agent-coordination`](031-durable-multi-agent-coordination.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
81
+ | [`030-agent-handoff-domain-and-durable-responsibility`](030-agent-handoff-domain-and-durable-responsibility.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. Runner ownership amended by [034-handoff-runner-coordination-ownership](034-handoff-runner-coordination-ownership.md); other V2 semantics remain. |
82
+ | [`031-durable-multi-agent-coordination`](031-durable-multi-agent-coordination.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. Runner ownership amended by [034-handoff-runner-coordination-ownership](034-handoff-runner-coordination-ownership.md); other V2 semantics remain. |
83
+ | [`032-storage-backend-composition`](032-storage-backend-composition.md) | Accepted | Yes | Separates raw Storage contracts/backends from domain Persistence by composition; replaces the Persistence subclass SPI and its facade-building helper. ADR-014 single transaction domain and ownership guarantees remain; [033-domain-persistence-ownership](033-domain-persistence-ownership.md) refines codec/repository ownership. |
84
+ | [`033-domain-persistence-ownership`](033-domain-persistence-ownership.md) | Amended | Yes | Domain-owned codecs, repositories, and result queries over the unchanged Storage SPI; explicit composition preserves one transaction domain. Error boundary refined by [043-storage-execution-constraint-notifications](043-storage-execution-constraint-notifications.md). |
85
+ | [`034-handoff-runner-coordination-ownership`](034-handoff-runner-coordination-ownership.md) | Accepted | Yes | H1 moves the public HandoffRunner to MultiAgent; Agent execution, Handoff records, and Runtime shutdown semantics are preserved. Further Handoff separation is deferred. |
86
+ | [`035-tool-executor-capability-ownership`](035-tool-executor-capability-ownership.md) | Accepted | Yes | T1 places the private default Tool executor beside Capability Base; public Tool identity, execution modes, Runtime injection, and Agent authorization/result ownership are preserved. |
87
+ | [`036-context-contract-ownership`](036-context-contract-ownership.md) | Accepted | Yes | C1 groups Context Policy/hook contracts, values, Manifest representation, and Plan validation in a collapsed directory; public Agent constants, extension protocols, and stored formats are preserved. |
88
+ | [`037-common-definition-ownership`](037-common-definition-ownership.md) | Amended | Yes | Defines the common responsibility group and initially extracts the shared base exception; [038-responsibility-based-source-layout](038-responsibility-based-source-layout.md) extends the extraction scope while preserving ownership rules and exception contracts. |
89
+ | [`038-responsibility-based-source-layout`](038-responsibility-based-source-layout.md) | Amended | Yes | Reserves the direct root for version/namespace loading, groups common definitions and feature implementation/contracts, and preserves canonical constants and lifecycle loading through explicit Zeitwerk roots. ADR-039 separates cross-owner Runtime lifecycle coordination. |
90
+ | [`039-runtime-configuration-lifecycle-ownership`](039-runtime-configuration-lifecycle-ownership.md) | Amended | Yes | Separates application Runtime reset and configuration replacement into runtime_composition; configuration access and Engine mechanics retain their own ownership and existing API behavior. ADR-040 separates concrete-default selection without changing Runtime reset. |
91
+ | [`040-configuration-default-composition`](040-configuration-default-composition.md) | Accepted | Yes | Settings consume internal fresh-instance factories; runtime_composition selects and binds the concrete adapter/tracer defaults. Preserves Configuration.new and the adapter SPI. |
92
+ | [`041-feature-owned-identity-registries`](041-feature-owned-identity-registries.md) | Accepted | Yes | Agent and MultiAgent own identity registries; Runtime retains them through generic lookup, drain/wait, and optional finalization. Preserves product APIs and single-owner lifetime; Execution state is separately assigned by ADR-042. |
93
+
94
+ | [`042-feature-owned-execution-state`](042-feature-owned-execution-state.md) | Accepted | Yes | Agent/Workflow own execution state; Engine retains generic receiver delivery, synchronization and shutdown boundaries. Single-writer and durable barriers remain. |
95
+ | [`043-storage-execution-constraint-notifications`](043-storage-execution-constraint-notifications.md) | Accepted | Yes | Raw backends report Storage-owned active-execution conflicts; feature repositories preserve public busy errors within the same transaction. Beta raw error SPI migration. |
96
+ | [`044-agent-default-and-one-shot-composition`](044-agent-default-and-one-shot-composition.md) | Accepted | Yes | Agent consumes an owner-defined fresh-Persistence factory; application composition selects the default and owns the unchanged one-shot API. |
97
+ | [`045-worker-input-restriction-ownership`](045-worker-input-restriction-ownership.md) | Accepted | Yes | Each restricted type declares an execution-boundary marker; authorization input validation preserves the existing rejection and opaque application-value contracts without enumerating feature types. |
98
+ | [`046-agent-responsibility-layout-and-shared-records`](046-agent-responsibility-layout-and-shared-records.md) | Amended | Yes | Agent responsibility directories preserve constants; shared record encoding, saved context reads and live restoration have separate owners. Continuation control refined by [047-recovered-execution-continuation-contract](047-recovered-execution-continuation-contract.md); deferred SharedState ownership resolved by [053-shared-state-coordination-ownership](053-shared-state-coordination-ownership.md). |
99
+ | [`047-recovered-execution-continuation-contract`](047-recovered-execution-continuation-contract.md) | Accepted | Yes | Recovery hands semantic commands to the execution owner; EventLoop identity/revision checks and shared session registration replace private control calls. |
100
+ | [`048-dispatch-preparation-worker-ownership`](048-dispatch-preparation-worker-ownership.md) | Accepted | Yes | Dispatch worker owns prerequisite persistence and readback; the execution owner retains EventLoop validation, apply and dispatch. Operation-specific boundaries and purpose-level method bodies are preserved. |
101
+ | [`049-initial-preparation-worker-ownership`](049-initial-preparation-worker-ownership.md) | Accepted | Yes | Initial preparation and preparing recovery share a persistence worker; admission outcomes, commit certainty and EventLoop ownership stay distinct. Pure failure classification is shared without sharing transaction control. |
102
+ | [`050-approval-resume-snapshot-and-commit-ownership`](050-approval-resume-snapshot-and-commit-ownership.md) | Accepted | Yes | Validated approval commands own immutable recovery snapshots. A worker commits decision, Execution and Root; the execution owner retains admission, live state and session resumption. |
103
+ | [`051-execution-outcome-worker-ownership`](051-execution-outcome-worker-ownership.md) | Accepted | Yes | Ordinary and Handoff outcome workers own atomic persistence and operation-specific readback; EventLoop retains result authority and delivery. |
104
+ | [`052-tool-invocation-restoration-ownership`](052-tool-invocation-restoration-ownership.md) | Accepted | Yes | ToolInvocation owns saved state application; Recovery retains snapshot decoding and identity matching. Existing restoration and replay rules are preserved. |
105
+ | [`053-shared-state-coordination-ownership`](053-shared-state-coordination-ownership.md) | Accepted | Yes | Moves Experimental SharedState and its invocation-local store to MultiAgent without an old-name alias; preserves coordination behavior and generated definition identity. Resolves the deferred SharedState ownership in ADR-046. |
106
+ | [`054-workflow-terminal-save-single-owner`](054-workflow-terminal-save-single-owner.md) | Accepted | Yes | Consolidates the active F1-aware terminal save in WorkflowRunner and removes its private prepend override. Amends ADR-038 loading; preserves the durable barrier and leaves FSMSession policy ownership as separate work. |
107
+ | [`055-terminal-observer-failure-settlement`](055-terminal-observer-failure-settlement.md) | Accepted | Yes | Keeps the error path open until terminal stable notification returns. Observer failure settles the caller and releases admission without retrying or undoing an already confirmed save. Clarifies ADR-026; W2b ownership extraction remains separate. |
108
+ | [`056-workflow-terminal-policy-ownership`](056-workflow-terminal-policy-ownership.md) | Accepted | Yes | Workflow owns persistence-result interpretation through a private policy; Engine retains generic session gating and complete/fail/retire actions. Preserves ADR-026/055 ordering and uncertainty without a public plugin API. |
109
+ | [`057-storage-transaction-boundaries`](057-storage-transaction-boundaries.md) | Accepted | Yes | Enforces active-owner exclusion on InMemory updates, validates SQL Journal batches before writes and defines explicit nested savepoints with propagated failures. Preserves the existing SPI and record formats; the neutral SPI remains separate work. |
110
+
111
+ | [`058-neutral-storage-primitives`](058-neutral-storage-primitives.md) | Accepted | Yes | Neutral Records/Streams/Blobs SPI 2 and scoped transaction lifecycle; amends 032, 033, 043 and 057. |
83
112
 
84
113
  ## Legacy duplicate `011`
85
114
 
@@ -1,5 +1,11 @@
1
1
  # Phronomy Durable Semantic Coordination — Implementation Design V2
2
2
 
3
+ > Runner namespace update (2026-09-18): this document preserves the V2
4
+ > implementation/migration record. The current Runner is
5
+ > `Phronomy::MultiAgent::HandoffRunner` under
6
+ > [ADR-034](../../decisions/034-handoff-runner-coordination-ownership.md).
7
+ > Handoff and HandoffPolicy remain in Agent at this stage.
8
+
3
9
  ## 0. Status and authority
4
10
 
5
11
  **Accepted implementation design — V2 revision 2 (2026-09-06).**
@@ -1,5 +1,11 @@
1
1
  # Durable Semantic Coordination V2 revision 2 — Implementation report
2
2
 
3
+ > Runner namespace update (2026-09-18): this document preserves the V2
4
+ > implementation/migration record. The current Runner is
5
+ > `Phronomy::MultiAgent::HandoffRunner` under
6
+ > [ADR-034](../../decisions/034-handoff-runner-coordination-ownership.md).
7
+ > Handoff and HandoffPolicy remain in Agent at this stage.
8
+
3
9
  作成日: 2026-09-07。設計承認日: 2026-09-06。
4
10
  対象baseline: `5472116cd99a63ec27875024c955ea82be612d6b`。
5
11
  承認済みADR-029/030/031とRC-01〜05に対する新規実装です。
data/docs/features.md CHANGED
@@ -20,7 +20,7 @@ for production deployments.
20
20
  | **Workflow** — Stateful, branching workflows with `wait_state` and explicit events | Stable |
21
21
  | **Agent** — Stateful ReAct-style agents with stable `agent_id`, one mutable live owner per Runtime, persistence-backed execution state, canonical history, and conversation context | Stable |
22
22
  | **Tool authoring façade** — `Phronomy::Tool::Base` is the public authoring name for the existing Capability base class; the legacy namespace remains compatible | Beta |
23
- | **Unified Persistence** — One durable backend abstraction for Agent state and Workflow `workflow_states`; live Agent/Workflow state remains owned by Runtime/session authority between durable commits; custom backends implement the documented Backend SPI and repository/transaction semantics | Beta |
23
+ | **Unified Persistence** — One transaction domain for Agent, Team, and Workflow state; a domain-facing `Persistence` composes a record-oriented `Storage::Backend`; live Agent/Workflow state remains owned by Runtime/session authority between durable commits; custom backends implement the documented Backend SPI, including Storage-owned active-execution constraint notifications translated by domain repositories, and repository/transaction semantics | Beta |
24
24
  | **LLMAdapter SPI** — `Phronomy::LLMAdapter::Base#complete` / `#stream` define the Beta call-adapter extension boundary; Phronomy owns async/offload wrapping | Beta |
25
25
  | **Before-Large-Language-Model (LLM) Input Hook** — Three-tier per-call LLM input customization via `before_llm_input` and `LLMInputPatch` | Stable |
26
26
  | **Context Management** — Journal + Context Policy + per-LLM-call Manifest with token-budget-aware selection and protocol-safe Tool Call / Tool message dependencies | Stable |
@@ -79,14 +79,20 @@ rather than implicitly inheriting the parent revision. The Stable
79
79
 
80
80
  ## Agent and workflow patterns
81
81
 
82
+ Agent Tool batches use a single ordinary RubyLLM chat path. Agent owns Tool
83
+ authorization, dispatch and the barrier before the next Provider request;
84
+ concurrency remains governed by Tool execution modes and Runtime capacity.
85
+ The obsolete `parallel_tool_execution` configuration accessor has been removed.
86
+ See the [migration guide](migrations/parallel-tool-chat-removal.md).
87
+
82
88
  | Feature | Stability |
83
89
  |---|---|
84
90
  | **Workflow asynchronous pattern** — Start async work, return immediately, and continue through `Workflow#signal` | Beta |
85
- | **Durable Agent Handoff** — `Agent::Handoff` and `Agent::HandoffRunner` persist responsibility, immutable Context and exact Target reservation in one Persistence domain; current graph wiring is required for continuation | Beta |
91
+ | **Durable Handoff** — `Agent::Handoff` and `MultiAgent::HandoffRunner` persist responsibility, immutable Context and exact Target reservation in one Persistence domain; current graph wiring is required for continuation | Beta |
86
92
  | **GeneratorVerifier** — Generator-Verifier loop with injectable prompts/parsers | Beta |
87
93
  | **`Phronomy::MultiAgent::Orchestrator`** — Parallel subagent dispatch, fan-out, and `subagent` DSL | Beta |
88
94
  | **`Phronomy::MultiAgent::TeamCoordinator`** — LLM coordinator with stateful worker Agents | Beta |
89
- | **SharedState** — Peer-agent shared-state coordination | Experimental |
95
+ | **`Phronomy::MultiAgent::SharedState`** — Sequential peer-agent coordination through an invocation-local findings store; see the [namespace migration](migrations/shared-state-multi-agent.md) | Experimental |
90
96
  | **Human-in-the-loop approval** — durable suspension publishes `:approval_required` through the Agent listener; `approve` / `approve_async` resumes the same logical `execution_id` with a fresh FSMSession incarnation | Beta |
91
97
  | **`tool_approval_policy`** — Application-defined allow/approve/reject policy using a value-only `ApprovalEvaluationRequest` without live Agent/Tool references | Beta |
92
98
 
@@ -85,7 +85,7 @@ application does not need to pass the previous `messages` array back into every
85
85
  invocation.
86
86
 
87
87
  ```ruby
88
- persistence = Phronomy::Persistence::InMemory.new
88
+ persistence = Phronomy::Persistence.in_memory
89
89
 
90
90
  agent = ResearchAgent.create(
91
91
  agent_id: "research-session-42",
@@ -115,7 +115,7 @@ A Runtime has at most one mutable live Agent object for an `agent_id`. If the
115
115
  Agent is already live, repeated `load` returns that exact Ruby object and does
116
116
  not reload Persistence. If it is not live, `load` hydrates the durable Agent
117
117
  once. Loading an ID that does not exist durably raises
118
- `Persistence::NotFoundError`.
118
+ `Storage::NotFoundError`.
119
119
 
120
120
  Use `get` when only a process-local lookup is wanted:
121
121
 
@@ -131,7 +131,7 @@ While the Agent is live, it owns its current AgentRoot/Journal view and
131
131
  Runtime/EventLoop owns process-local identity/admission/execution authority.
132
132
  Phronomy persists snapshots at defined durability boundaries but does not reload
133
133
  mutable Agent/Execution/Journal state before every LLM or Tool step. A conflicting
134
- external durable write is surfaced as `Persistence::ConflictError` rather than
134
+ external durable write is surfaced as `Storage::ConflictError` rather than
135
135
  silently merged into the live instance.
136
136
 
137
137
  The active transcript and Knowledge views can be advanced independently without
@@ -250,7 +250,7 @@ end
250
250
  write_draft = ->(state) { state.merge(draft: "Draft content") }
251
251
  review_draft = ->(state) { state.merge(feedback: "Feedback on: #{state.draft}") }
252
252
 
253
- persistence = Phronomy::Persistence::InMemory.new
253
+ persistence = Phronomy::Persistence.in_memory
254
254
 
255
255
  workflow = Phronomy::Workflow.define(
256
256
  ReviewContext,
@@ -16,6 +16,11 @@ follow the current contracts documented in
16
16
  | `InvocationContext#provider_limits` | Configure the provider client directly |
17
17
  | `stream_queue_max_size` | No replacement; the shared EventLoop queue is unbounded by design. Monitor `Metrics.snapshot[:event_loop_queue_depth]` instead |
18
18
 
19
+ The historical `parallel_tool_execution` switch mentioned above was subsequently
20
+ removed by the architecture refactor. Current code should follow the
21
+ [Chat migration guide](parallel-tool-chat-removal.md); it is not an on/off
22
+ control for Agent Tool concurrency.
23
+
19
24
  ## Timeout ownership
20
25
 
21
26
  Phronomy owns logical lifecycle deadlines and cooperative cancellation. Provider,
@@ -1,5 +1,11 @@
1
1
  # Durable semantic coordination V2 migration
2
2
 
3
+ > Runner namespace update (2026-09-18): this document preserves the V2
4
+ > implementation/migration record. The current Runner is
5
+ > `Phronomy::MultiAgent::HandoffRunner` under
6
+ > [ADR-034](../decisions/034-handoff-runner-coordination-ownership.md).
7
+ > Handoff and HandoffPolicy remain in Agent at this stage.
8
+
3
9
  This Beta clean break applies to baseline `5472116cd99a63ec27875024c955ea82be612d6b`.
4
10
 
5
11
  | Previous surface | Current surface |
@@ -0,0 +1,35 @@
1
+ # HandoffRunner moves to MultiAgent
2
+
3
+ This change applies to H1 on `refactor/architecture` after core commit
4
+ `fe2ad7cea6945a240858b18645dc4ae285e8ce64`. The released 0.26.0 gem does not
5
+ yet provide this new Runner name.
6
+
7
+ | Previous API | API on this refactoring branch |
8
+ |---|---|
9
+ | `Phronomy::Agent::HandoffRunner` | `Phronomy::MultiAgent::HandoffRunner` |
10
+ | `Phronomy::Agent::Handoff` | Unchanged |
11
+ | `Phronomy::Agent::HandoffPolicy` | Unchanged |
12
+
13
+ The previous Runner name is removed without an alias. Update direct `require`
14
+ paths from `phronomy/agent/handoff_runner` to `phronomy/multi_agent/handoff_runner`
15
+ if used; ordinary `require "phronomy"` continues to use Zeitwerk.
16
+
17
+ Runner initialization still accepts `main_agent:` and `handoffs:`. Its `invoke`,
18
+ `cancel` and `result` methods, `main_agent`/`handoffs` readers and `MAX_HANDOFFS`
19
+ constant retain their behavior. Existing Handoff edges and Policy objects remain
20
+ in the Agent namespace during this first step.
21
+
22
+ Update the core and examples together. When using examples from the corresponding
23
+ refactoring branch, set `PHRONOMY_PATH` to the matching local core checkout before
24
+ resolving bundles or running verification. The examples API preflight rejects an
25
+ older core and checks exact removed constants without mistaking
26
+ `MultiAgent::HandoffRunner` for `MultiAgent::Handoff`.
27
+
28
+ No persisted-record migration or SQL schema change is required. Existing
29
+ HandoffState, Context and execution records are read using the same format,
30
+ identity and revision rules. Recovery still requires compatible current Agent
31
+ definitions and Handoff graph wiring; changing the Runner namespace does not
32
+ relax that requirement.
33
+
34
+ The ownership rationale and remaining work are recorded in
35
+ [ADR-034](../decisions/034-handoff-runner-coordination-ownership.md).
@@ -0,0 +1,43 @@
1
+ # Migrating to neutral Storage SPI 2 (Refactor 35)
2
+
3
+ Apply matching core and examples changes together. Existing SQL databases need
4
+ no schema or payload migration. Applications continue using Persistence domain
5
+ repositories. Direct Backend implementations and callers must migrate.
6
+
7
+ | Previous extension point | SPI 2 |
8
+ |---|---|
9
+ | Eight repository keywords to Backend | `resources: [Resource, ...]` |
10
+ | `backend.agents`, `backend.executions`, etc. | `backend.view.records(resource)`; domain names stay on Persistence |
11
+ | Journal raw repository | `view.streams(resource)` with `Entry::Append` inputs |
12
+ | Raw ContentStore repository | `view.blobs(resource)`; `ContentStore::StoredContents` owns digest behavior |
13
+ | `Storage::Repositories` transaction view | `Storage::View` bound to a transaction scope |
14
+ | `assert_agent_watermark!` on raw Backend | Agent-owned Watermark composes GuardRef, RevisionIs and StreamHeadIs |
15
+ | ActiveExecutionConflictError | UniqueConstraintError with exact resource/constraint; NoRows condition for idle |
16
+ | Three domain-named raw capabilities | spi_version 2 and six neutral capabilities |
17
+
18
+ A driver implements the protected physical operations used by Records, Streams,
19
+ Blobs and guards, plus `storage_transaction`. Reuse the common scope lifecycle;
20
+ do not override `transaction` with a view that bypasses it. Return independent
21
+ Entry values and never decode domain payload to reconstruct index metadata.
22
+ A non-subclass backend must provide the same public protocol and semantics.
23
+ The SQL reference driver receives immutable physical mappings independently of
24
+ resource declarations; no resource-ID case switch selects domain SQL behavior.
25
+
26
+ Repository wrappers obtained inside a transaction expire with that transaction.
27
+ Do not retain them in application objects. Cache root repositories/handles when
28
+ needed: they route to the current transaction on the same thread. Recover from
29
+ an operation failure only outside an explicit inner savepoint. Catching a failure
30
+ inside its failed scope prevents further work and commit. Complete transaction
31
+ blocks normally; return/break/throw raises TransactionError after rollback.
32
+
33
+ Initial Workflow/Handoff saves still use expected_revision nil and return the
34
+ existing domain result. Storage Records itself requires explicit insert versus
35
+ replace. Missing required parent records now consistently raise NotFoundError;
36
+ this closes prior InMemory/SQLite/PG differences for orphan raw writes. Nonempty
37
+ keys and text attributes must be valid UTF-8 without NUL. Nullable unique keys
38
+ are distinct. Domain Journal limit zero remains an empty result.
39
+
40
+ Run the shipped domain and neutral conformance suites, the dedicated SPI 2/RBS
41
+ checks and each physical driver's concurrency/failure tests. For PostgreSQL run
42
+ the real server gate with the matching candidate core, then verify fresh-pool
43
+ reload. Existing S2a CI is historical evidence, not validation of this SPI.
@@ -0,0 +1,49 @@
1
+ # Removal of the internal parallel Chat path
2
+
3
+ This change belongs to the incremental architecture refactor following 0.26.0.
4
+ It does not publish a new gem version.
5
+
6
+ ## Application changes
7
+
8
+ Remove assignments to `Phronomy.configuration.parallel_tool_execution`, including
9
+ assignments inside `Phronomy.configure`. Both the reader and writer are removed;
10
+ there is no compatibility accessor or replacement switch. The former setting
11
+ selected a Chat subclass but did not gate concurrency in the Agent-owned Tool
12
+ execution path. A previous value of `false` did not guarantee serial execution.
13
+
14
+ `Phronomy::MultiAgent::ParallelToolChat` and its file are removed. Do not require
15
+ the old file or instantiate that private class. No `Agent::ParallelToolChat`
16
+ replacement or alias is introduced. Applications that need Agent-owned Tool
17
+ approval, cancellation and execution tracking should enter through the Agent
18
+ invoke/stream APIs. Direct RubyLLM chat use is outside that Agent lifecycle.
19
+
20
+ ## Retained behavior
21
+
22
+ Both complete and streaming calls use ordinary `RubyLLM::Chat`. Before the first
23
+ Tool body runs, the existing RubyLLM callback lets Agent capture every Tool call
24
+ in the complete assistant message. Agent manages Tool authorization, approval,
25
+ dispatch, cancellation and result collection under ADR-010 and ADR-024.
26
+
27
+ On success, every result is associated with its original call ID and recorded
28
+ in request order. All results are included in the next Provider request, after
29
+ the batch completes. Runtime capacity and each Tool's execution mode still
30
+ determine how work can overlap. This change does not introduce a serial Tool
31
+ mode or a partial-result Provider continuation.
32
+
33
+ The old direct-Chat fallback and its RubyLLM-specific callback/Halt behavior are
34
+ removed with the private class. They are not a second supported Agent execution
35
+ API. Agent-level event callbacks keep their existing contract.
36
+
37
+ ## Existing stored records
38
+
39
+ New standard model-config records omit `parallel_tool_execution`. Existing
40
+ ContentStore records and manifest hashes are not rewritten. An existing record
41
+ may still contain that field; materialization preserves its bytes and Agent's
42
+ Chat builder ignores it, just as it ignores other unused model-config fields.
43
+ There is no manifest version change or compatibility branch that reinstates the
44
+ removed Chat class.
45
+
46
+ The regression suite checks materialization and Chat construction for stored
47
+ records containing both historical boolean values. Existing recovery tests
48
+ continue to cover the supported recovery contracts; this change does not add
49
+ execution-resumption or external-effect guarantees.