phronomy 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (557) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +9 -9
  3. data/CHANGELOG.md +92 -0
  4. data/CONTRIBUTING.md +8 -8
  5. data/README.md +13 -3
  6. data/VERIFY.sh +27 -27
  7. data/benchmark/bench_agent_invoke.rb +26 -47
  8. data/benchmark/bench_context_assembler.rb +17 -15
  9. data/benchmark/bench_regression.rb +1 -1
  10. data/benchmark/bench_tool_schema.rb +1 -1
  11. data/docs/architecture/agent-chat-and-state-ownership.md +153 -0
  12. data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
  13. data/docs/architecture/agent-context.md +4 -2
  14. data/docs/architecture/agent-transition-ownership.md +13 -0
  15. data/docs/architecture/backend-groups.md +152 -0
  16. data/docs/architecture/before-llm-input.md +9 -3
  17. data/docs/architecture/context-management.md +31 -1
  18. data/docs/architecture/context-preparation-steps.md +90 -0
  19. data/docs/architecture/entry-action-and-team-wording.md +72 -0
  20. data/docs/architecture/execution-abstraction-review.md +88 -0
  21. data/docs/architecture/execution-boundaries.md +28 -0
  22. data/docs/architecture/execution-metadata-and-values.md +86 -0
  23. data/docs/architecture/generator-verifier-ownership.md +111 -0
  24. data/docs/architecture/multi-agent-handoff.md +11 -4
  25. data/docs/architecture/persistence-refactoring-plan.md +50 -0
  26. data/docs/architecture/persistence.md +45 -4
  27. data/docs/architecture/r8-unit1.md +104 -0
  28. data/docs/architecture/r8-unit10.md +72 -0
  29. data/docs/architecture/r8-unit11.md +71 -0
  30. data/docs/architecture/r8-unit12.md +67 -0
  31. data/docs/architecture/r8-unit13.md +61 -0
  32. data/docs/architecture/r8-unit14.md +72 -0
  33. data/docs/architecture/r8-unit15.md +65 -0
  34. data/docs/architecture/r8-unit16.md +54 -0
  35. data/docs/architecture/r8-unit17.md +73 -0
  36. data/docs/architecture/r8-unit18.md +92 -0
  37. data/docs/architecture/r8-unit19.md +61 -0
  38. data/docs/architecture/r8-unit2.md +55 -0
  39. data/docs/architecture/r8-unit20.md +51 -0
  40. data/docs/architecture/r8-unit21.md +79 -0
  41. data/docs/architecture/r8-unit22.md +74 -0
  42. data/docs/architecture/r8-unit23.md +81 -0
  43. data/docs/architecture/r8-unit3.md +130 -0
  44. data/docs/architecture/r8-unit4.md +79 -0
  45. data/docs/architecture/r8-unit5.md +115 -0
  46. data/docs/architecture/r8-unit6.md +71 -0
  47. data/docs/architecture/r8-unit7.md +70 -0
  48. data/docs/architecture/r8-unit8.md +78 -0
  49. data/docs/architecture/r8-unit9.md +73 -0
  50. data/docs/architecture/refactoring-closure.md +343 -0
  51. data/docs/architecture/remaining-refactoring-plan.md +390 -0
  52. data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
  53. data/docs/architecture/storage-execution-boundaries.md +54 -0
  54. data/docs/architecture/tool-schema-recording-gap.md +56 -0
  55. data/docs/architecture/tracing.md +2 -2
  56. data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
  57. data/docs/architecture.md +222 -0
  58. data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
  59. data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
  60. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
  61. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
  62. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
  63. data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
  64. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +7 -0
  65. data/docs/decisions/031-durable-multi-agent-coordination.md +7 -0
  66. data/docs/decisions/032-storage-backend-composition.md +85 -0
  67. data/docs/decisions/033-domain-persistence-ownership.md +79 -0
  68. data/docs/decisions/034-handoff-runner-coordination-ownership.md +78 -0
  69. data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
  70. data/docs/decisions/036-context-contract-ownership.md +86 -0
  71. data/docs/decisions/037-common-definition-ownership.md +62 -0
  72. data/docs/decisions/038-responsibility-based-source-layout.md +145 -0
  73. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +82 -0
  74. data/docs/decisions/040-configuration-default-composition.md +105 -0
  75. data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
  76. data/docs/decisions/042-feature-owned-execution-state.md +106 -0
  77. data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
  78. data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
  79. data/docs/decisions/045-worker-input-restriction-ownership.md +104 -0
  80. data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
  81. data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
  82. data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
  83. data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
  84. data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
  85. data/docs/decisions/051-execution-outcome-worker-ownership.md +153 -0
  86. data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
  87. data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
  88. data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
  89. data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
  90. data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
  91. data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
  92. data/docs/decisions/058-neutral-storage-primitives.md +83 -0
  93. data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
  94. data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
  95. data/docs/decisions/061-persistence-failure-contracts.md +89 -0
  96. data/docs/decisions/062-content-store-service.md +52 -0
  97. data/docs/decisions/063-execution-contracts-and-services.md +88 -0
  98. data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
  99. data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
  100. data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
  101. data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
  102. data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
  103. data/docs/decisions/README.md +52 -6
  104. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
  105. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
  106. data/docs/execution-boundaries-preview.md +45 -0
  107. data/docs/features.md +16 -5
  108. data/docs/getting-started.md +11 -8
  109. data/docs/migrations/0.15.md +5 -0
  110. data/docs/migrations/0.22.md +2 -2
  111. data/docs/migrations/durable-semantic-coordination-v2.md +8 -0
  112. data/docs/migrations/handoff-runner-multi-agent.md +37 -0
  113. data/docs/migrations/neutral-storage-spi.md +43 -0
  114. data/docs/migrations/parallel-tool-chat-removal.md +49 -0
  115. data/docs/migrations/persistence-failure-contracts.md +67 -0
  116. data/docs/migrations/r8-unit10.md +36 -0
  117. data/docs/migrations/r8-unit11.md +33 -0
  118. data/docs/migrations/r8-unit12.md +31 -0
  119. data/docs/migrations/r8-unit13.md +36 -0
  120. data/docs/migrations/r8-unit14.md +31 -0
  121. data/docs/migrations/r8-unit15.md +31 -0
  122. data/docs/migrations/r8-unit16.md +26 -0
  123. data/docs/migrations/r8-unit17.md +28 -0
  124. data/docs/migrations/r8-unit18.md +29 -0
  125. data/docs/migrations/r8-unit19.md +28 -0
  126. data/docs/migrations/r8-unit20.md +24 -0
  127. data/docs/migrations/r8-unit21.md +28 -0
  128. data/docs/migrations/r8-unit22.md +29 -0
  129. data/docs/migrations/r8-unit23.md +20 -0
  130. data/docs/migrations/r8-unit4.md +67 -0
  131. data/docs/migrations/r8-unit5.md +75 -0
  132. data/docs/migrations/r8-unit6.md +109 -0
  133. data/docs/migrations/r8-unit7.md +31 -0
  134. data/docs/migrations/r8-unit8.md +33 -0
  135. data/docs/migrations/r8-unit9.md +28 -0
  136. data/docs/migrations/shared-state-multi-agent.md +44 -0
  137. data/docs/migrations/storage-async-client.md +103 -0
  138. data/docs/migrations/storage-backend-composition.md +117 -0
  139. data/docs/migrations/storage-transaction-boundaries.md +74 -0
  140. data/docs/migrations/vector-async-clients.md +110 -0
  141. data/docs/persistence-backends.md +190 -215
  142. data/docs/runtime-and-concurrency.md +142 -32
  143. data/lib/phronomy/agent/admission.rb +78 -0
  144. data/lib/phronomy/{agent_already_exists_error.rb → agent/agent_already_exists_error.rb} +2 -0
  145. data/lib/phronomy/{agent_busy_error.rb → agent/agent_busy_error.rb} +2 -0
  146. data/lib/phronomy/{agent_purged_error.rb → agent/agent_purged_error.rb} +2 -0
  147. data/lib/phronomy/agent/api/agent.rb +17 -0
  148. data/lib/phronomy/{execution_rehydration_required_error.rb → agent/api/execution_rehydration_required_error.rb} +2 -0
  149. data/lib/phronomy/agent/async_event_api.rb +38 -33
  150. data/lib/phronomy/agent/base.rb +106 -294
  151. data/lib/phronomy/agent/before_llm_input.rb +64 -0
  152. data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
  153. data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
  154. data/lib/phronomy/agent/context_importer.rb +2 -2
  155. data/lib/phronomy/agent/{context_assembler.rb → context_preparation.rb} +157 -288
  156. data/lib/phronomy/agent/control_request.rb +21 -0
  157. data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
  158. data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +32 -63
  159. data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
  160. data/lib/phronomy/agent/execution/dispatch_preparation.rb +195 -0
  161. data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +43 -23
  162. data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +8 -5
  163. data/lib/phronomy/agent/execution/execution_coordinator.rb +1744 -0
  164. data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
  165. data/lib/phronomy/agent/execution/execution_metadata.rb +54 -0
  166. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +288 -0
  167. data/lib/phronomy/agent/execution/execution_registry.rb +463 -0
  168. data/lib/phronomy/agent/execution/execution_session_runner.rb +113 -0
  169. data/lib/phronomy/agent/execution/initial_preparation.rb +323 -0
  170. data/lib/phronomy/agent/execution/invocation_actions.rb +368 -0
  171. data/lib/phronomy/agent/execution/invocation_transitions.rb +124 -0
  172. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
  173. data/lib/phronomy/agent/execution_change.rb +161 -0
  174. data/lib/phronomy/agent/execution_environment.rb +36 -0
  175. data/lib/phronomy/agent/execution_extension_state.rb +21 -0
  176. data/lib/phronomy/agent/execution_observation.rb +35 -0
  177. data/lib/phronomy/agent/filterable.rb +182 -0
  178. data/lib/phronomy/agent/{handoff_context.rb → handoff/transfer_context.rb} +6 -6
  179. data/lib/phronomy/agent/{handoff_projection.rb → handoff/transfer_projection.rb} +14 -33
  180. data/lib/phronomy/agent/handoff_error.rb +7 -0
  181. data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
  182. data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
  183. data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
  184. data/lib/phronomy/agent/knowledge_item.rb +13 -0
  185. data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
  186. data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
  187. data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -15
  188. data/lib/phronomy/agent/persistence/agent_repository.rb +69 -0
  189. data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
  190. data/lib/phronomy/agent/persistence/codec.rb +338 -0
  191. data/lib/phronomy/agent/persistence/execution_repository.rb +124 -0
  192. data/lib/phronomy/agent/persistence/journal_repository.rb +63 -0
  193. data/lib/phronomy/agent/persistence/records.rb +33 -0
  194. data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
  195. data/lib/phronomy/agent/persistence/storage_schema.rb +29 -0
  196. data/lib/phronomy/agent/persistence/watermark.rb +29 -0
  197. data/lib/phronomy/agent/recovery/invocation_restorer.rb +124 -0
  198. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +28 -51
  199. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +50 -55
  200. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +38 -43
  201. data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +26 -23
  202. data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
  203. data/lib/phronomy/agent/recovery/recovery_support.rb +224 -0
  204. data/lib/phronomy/agent/reserved_execution.rb +16 -0
  205. data/lib/phronomy/agent/retention.rb +17 -0
  206. data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
  207. data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
  208. data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
  209. data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
  210. data/lib/phronomy/agent/{ruby_llm_materializer.rb → runtime_input.rb} +19 -39
  211. data/lib/phronomy/agent/saved_context_reader.rb +55 -0
  212. data/lib/phronomy/agent/settings.rb +47 -0
  213. data/lib/phronomy/agent/state_writer.rb +166 -0
  214. data/lib/phronomy/agent/store.rb +253 -0
  215. data/lib/phronomy/{stream_callback_error.rb → agent/stream_callback_error.rb} +2 -0
  216. data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
  217. data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
  218. data/lib/phronomy/agent/tool_execution/tool_binding.rb +30 -0
  219. data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +114 -248
  220. data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
  221. data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
  222. data/lib/phronomy/common/configuration_error.rb +7 -0
  223. data/lib/phronomy/common/error.rb +5 -0
  224. data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
  225. data/lib/phronomy/common/values/serializable.rb +32 -0
  226. data/lib/phronomy/configuration/runtime_settings.rb +49 -0
  227. data/lib/phronomy/content_store/storage_schema.rb +12 -0
  228. data/lib/phronomy/content_store/stored_contents.rb +44 -0
  229. data/lib/phronomy/context/assembly.rb +202 -0
  230. data/lib/phronomy/{context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +5 -1
  231. data/lib/phronomy/context/candidate.rb +51 -0
  232. data/lib/phronomy/context/constraint.rb +47 -0
  233. data/lib/phronomy/{agent → context}/context_plan.rb +2 -2
  234. data/lib/phronomy/{agent → context}/context_plan_validator.rb +3 -3
  235. data/lib/phronomy/{agent → context}/context_policy.rb +1 -1
  236. data/lib/phronomy/{agent → context}/context_policy_input.rb +7 -7
  237. data/lib/phronomy/{agent → context}/context_policy_input_builder.rb +1 -1
  238. data/lib/phronomy/context/default_policy.rb +140 -0
  239. data/lib/phronomy/context/final_budget_validator.rb +33 -0
  240. data/lib/phronomy/{agent → context}/llm_input_build_context.rb +2 -2
  241. data/lib/phronomy/{agent → context}/llm_input_manifest.rb +21 -21
  242. data/lib/phronomy/{agent → context}/llm_input_patch.rb +3 -3
  243. data/lib/phronomy/context/manifest_error.rb +10 -0
  244. data/lib/phronomy/context/prompt_template.rb +98 -0
  245. data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
  246. data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
  247. data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
  248. data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
  249. data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
  250. data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
  251. data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
  252. data/lib/phronomy/embeddings/async/async_client.rb +44 -0
  253. data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +48 -0
  254. data/lib/phronomy/embeddings/base.rb +43 -0
  255. data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
  256. data/lib/phronomy/embeddings/transport_error.rb +11 -0
  257. data/lib/phronomy/engine/concurrency/offload_pool.rb +39 -20
  258. data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
  259. data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +1 -1
  260. data/lib/phronomy/engine/event_loop.rb +164 -630
  261. data/lib/phronomy/engine/execution_binding.rb +23 -0
  262. data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
  263. data/lib/phronomy/engine/fsm_protocol.rb +9 -0
  264. data/lib/phronomy/engine/fsm_session.rb +37 -30
  265. data/lib/phronomy/engine/metrics.rb +28 -0
  266. data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
  267. data/lib/phronomy/engine/runtime.rb +104 -95
  268. data/lib/phronomy/engine/terminal_decision.rb +7 -0
  269. data/lib/phronomy/execution/async_operation.rb +41 -0
  270. data/lib/phronomy/execution/backpressure_error.rb +7 -0
  271. data/lib/phronomy/{blocking.rb → execution/blocking.rb} +2 -2
  272. data/lib/phronomy/execution/cancellation_error.rb +7 -0
  273. data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +5 -1
  274. data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
  275. data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
  276. data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
  277. data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
  278. data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
  279. data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
  280. data/lib/phronomy/execution/concurrency/worker_input_restricted.rb +14 -0
  281. data/lib/phronomy/execution/event_loop_reentrancy_error.rb +8 -0
  282. data/lib/phronomy/{execution.rb → execution/execution.rb} +57 -30
  283. data/lib/phronomy/{execution_cancellation_error.rb → execution/execution_cancellation_error.rb} +2 -0
  284. data/lib/phronomy/execution/execution_receiver.rb +78 -0
  285. data/lib/phronomy/execution/execution_scope_state.rb +35 -0
  286. data/lib/phronomy/{execution_timeout_error.rb → execution/execution_timeout_error.rb} +2 -0
  287. data/lib/phronomy/{invalid_async_entry_action_error.rb → execution/invalid_async_entry_action_error.rb} +2 -0
  288. data/lib/phronomy/{invalid_async_transition_action_error.rb → execution/invalid_async_transition_action_error.rb} +2 -0
  289. data/lib/phronomy/{invalid_async_workflow_action_error.rb → execution/invalid_async_workflow_action_error.rb} +2 -0
  290. data/lib/phronomy/{invocation_context.rb → execution/invocation_context.rb} +0 -15
  291. data/lib/phronomy/execution/invocation_controls.rb +73 -0
  292. data/lib/phronomy/execution/pool_shutdown_error.rb +7 -0
  293. data/lib/phronomy/execution/recursion_limit_error.rb +7 -0
  294. data/lib/phronomy/execution/runnable.rb +24 -0
  295. data/lib/phronomy/execution/runtime_shutdown_error.rb +7 -0
  296. data/lib/phronomy/execution/runtime_shutdown_reentrancy_error.rb +7 -0
  297. data/lib/phronomy/execution/scheduler_reentrancy_error.rb +9 -0
  298. data/lib/phronomy/{engine → execution}/task_result.rb +7 -3
  299. data/lib/phronomy/execution/timeout_error.rb +7 -0
  300. data/lib/phronomy/execution/wait_policy.rb +24 -0
  301. data/lib/phronomy/filter/filter_block_error.rb +14 -0
  302. data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
  303. data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
  304. data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
  305. data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
  306. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
  307. data/lib/phronomy/generation/generator_verifier.rb +118 -0
  308. data/lib/phronomy/generation/low_confidence_error.rb +14 -0
  309. data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
  310. data/lib/phronomy/llm_adapter/authentication_error.rb +9 -0
  311. data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
  312. data/lib/phronomy/llm_adapter/base.rb +49 -68
  313. data/lib/phronomy/llm_adapter/context_length_error.rb +9 -0
  314. data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
  315. data/lib/phronomy/llm_adapter/message.rb +62 -0
  316. data/lib/phronomy/llm_adapter/rate_limit_error.rb +9 -0
  317. data/lib/phronomy/llm_adapter/request.rb +79 -0
  318. data/lib/phronomy/llm_adapter/response.rb +36 -0
  319. data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
  320. data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
  321. data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
  322. data/lib/phronomy/llm_adapter.rb +3 -16
  323. data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
  324. data/lib/phronomy/multi_agent/admission_registry.rb +15 -2
  325. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
  326. data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
  327. data/lib/phronomy/{agent → multi_agent}/handoff.rb +2 -2
  328. data/lib/phronomy/{agent → multi_agent}/handoff_capability_factory.rb +21 -2
  329. data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
  330. data/lib/phronomy/{agent → multi_agent}/handoff_policy.rb +1 -1
  331. data/lib/phronomy/multi_agent/handoff_runner.rb +156 -0
  332. data/lib/phronomy/{agent → multi_agent}/handoff_state.rb +2 -2
  333. data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
  334. data/lib/phronomy/multi_agent/persistence/codec.rb +75 -0
  335. data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
  336. data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
  337. data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
  338. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +124 -0
  339. data/lib/phronomy/multi_agent/persistence/team_repository.rb +69 -0
  340. data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
  341. data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
  342. data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
  343. data/lib/phronomy/multi_agent/store.rb +156 -0
  344. data/lib/phronomy/multi_agent/team_coordinator.rb +87 -75
  345. data/lib/phronomy/multi_agent/team_execution.rb +1 -1
  346. data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +5 -5
  347. data/lib/phronomy/multi_agent/team_root.rb +1 -1
  348. data/lib/phronomy/output_parser/parse_error.rb +7 -0
  349. data/lib/phronomy/persistence/content_repository.rb +26 -0
  350. data/lib/phronomy/persistence/errors.rb +16 -0
  351. data/lib/phronomy/persistence/migration/initial_format_migration.rb +21 -21
  352. data/lib/phronomy/persistence/persistence.rb +23 -0
  353. data/lib/phronomy/persistence/save_outcome.rb +24 -0
  354. data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
  355. data/lib/phronomy/persistence/storage_boundary.rb +32 -0
  356. data/lib/phronomy/persistence/transaction.rb +86 -0
  357. data/lib/phronomy/persistence_composition/storage_schema.rb +29 -0
  358. data/lib/phronomy/persistence_composition/stores.rb +34 -0
  359. data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
  360. data/lib/phronomy/runtime_composition/agent_defaults.rb +11 -0
  361. data/lib/phronomy/runtime_composition/configuration.rb +146 -0
  362. data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
  363. data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
  364. data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
  365. data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
  366. data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
  367. data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
  368. data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
  369. data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
  370. data/lib/phronomy/storage/async/async_client.rb +60 -0
  371. data/lib/phronomy/storage/backend.rb +107 -0
  372. data/lib/phronomy/storage/backends/in_memory.rb +157 -0
  373. data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
  374. data/lib/phronomy/storage/blobs.rb +31 -0
  375. data/lib/phronomy/storage/condition.rb +25 -0
  376. data/lib/phronomy/storage/condition_failed_error.rb +16 -0
  377. data/lib/phronomy/storage/conflict_error.rb +9 -0
  378. data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
  379. data/lib/phronomy/storage/entry.rb +33 -0
  380. data/lib/phronomy/storage/guard_ref.rb +13 -0
  381. data/lib/phronomy/storage/not_found_error.rb +9 -0
  382. data/lib/phronomy/storage/record_codec.rb +177 -0
  383. data/lib/phronomy/storage/records.rb +61 -0
  384. data/lib/phronomy/storage/resource.rb +126 -0
  385. data/lib/phronomy/storage/scope.rb +25 -0
  386. data/lib/phronomy/storage/serialization_error.rb +9 -0
  387. data/lib/phronomy/storage/streams.rb +44 -0
  388. data/lib/phronomy/storage/transaction_error.rb +10 -0
  389. data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
  390. data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
  391. data/lib/phronomy/storage/validation.rb +53 -0
  392. data/lib/phronomy/storage/view.rb +131 -0
  393. data/lib/phronomy/testing/eval/metrics.rb +1 -1
  394. data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
  395. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
  396. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
  397. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +54 -48
  398. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +1 -1
  399. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +1 -1
  400. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
  401. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +52 -46
  402. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
  403. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +124 -0
  404. data/lib/phronomy/testing/persistence_contract.rb +4 -0
  405. data/lib/phronomy/tool/authorization.rb +77 -0
  406. data/lib/phronomy/tool/base.rb +549 -9
  407. data/lib/phronomy/tool/call_request.rb +40 -0
  408. data/lib/phronomy/{agent/tool_definition_set.rb → tool/definition_set.rb} +16 -12
  409. data/lib/phronomy/tool/operation.rb +88 -0
  410. data/lib/phronomy/tool/schema.rb +214 -0
  411. data/lib/phronomy/tool/settings.rb +31 -0
  412. data/lib/phronomy/tool/tool_error.rb +7 -0
  413. data/lib/phronomy/{agent → tool}/tool_executor.rb +10 -7
  414. data/lib/phronomy/tools/agent.rb +22 -90
  415. data/lib/phronomy/tools/mcp.rb +21 -14
  416. data/lib/phronomy/tools/vector_search.rb +4 -4
  417. data/lib/phronomy/tracing/automatic.rb +11 -6
  418. data/lib/phronomy/tracing/base.rb +1 -1
  419. data/lib/phronomy/tracing/observation.rb +37 -0
  420. data/lib/phronomy/tracing/settings.rb +36 -0
  421. data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
  422. data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
  423. data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
  424. data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
  425. data/lib/phronomy/vector_store/base.rb +118 -49
  426. data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
  427. data/lib/phronomy/vector_store.rb +2 -17
  428. data/lib/phronomy/version.rb +1 -1
  429. data/lib/phronomy/workflow/completion.rb +11 -0
  430. data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +10 -8
  431. data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
  432. data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +5 -1
  433. data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
  434. data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +27 -0
  435. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +186 -0
  436. data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +145 -115
  437. data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
  438. data/lib/phronomy/workflow/persistence/codec.rb +153 -0
  439. data/lib/phronomy/workflow/persistence/state_repository.rb +63 -0
  440. data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
  441. data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +38 -0
  442. data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +156 -0
  443. data/lib/phronomy/workflow/runtime_binding/workflow_terminal_policy.rb +40 -0
  444. data/lib/phronomy.rb +97 -98
  445. data/scripts/api_snapshot.rb +36 -16
  446. data/scripts/storage_spi_snapshot.rb +36 -0
  447. data/sig/_private/phronomy/agent/settings.rbs +19 -0
  448. data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
  449. data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
  450. data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
  451. data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
  452. data/sig/_private/phronomy/tool/settings.rbs +13 -0
  453. data/sig/_private/phronomy/tracing/settings.rbs +15 -0
  454. data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
  455. data/sig/phronomy/agent/admission.rbs +19 -0
  456. data/sig/phronomy/agent/execution_contract.rbs +132 -0
  457. data/sig/phronomy/agent/execution_environment.rbs +20 -0
  458. data/sig/phronomy/agent/store.rbs +73 -0
  459. data/sig/phronomy/agent.rbs +14 -139
  460. data/sig/phronomy/common.rbs +7 -0
  461. data/sig/phronomy/content_store/contracts.rbs +13 -0
  462. data/sig/phronomy/context.rbs +152 -0
  463. data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
  464. data/sig/phronomy/embeddings/base.rbs +17 -0
  465. data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
  466. data/sig/phronomy/engine/control_bindings.rbs +11 -0
  467. data/sig/phronomy/engine/control_protocols.rbs +23 -0
  468. data/sig/phronomy/engine/execution_binding.rbs +6 -0
  469. data/sig/phronomy/engine/execution_receiver.rbs +15 -0
  470. data/sig/phronomy/engine/observability.rbs +13 -0
  471. data/sig/phronomy/execution/async_operation.rbs +7 -0
  472. data/sig/phronomy/execution/blocking.rbs +5 -0
  473. data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
  474. data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
  475. data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
  476. data/sig/phronomy/execution/control_protocols.rbs +18 -0
  477. data/sig/phronomy/execution/errors.rbs +7 -0
  478. data/sig/phronomy/execution/execution.rbs +41 -0
  479. data/sig/phronomy/execution/execution_receiver.rbs +40 -0
  480. data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
  481. data/sig/phronomy/execution/invocation_context.rbs +18 -0
  482. data/sig/phronomy/execution/invocation_controls.rbs +13 -0
  483. data/sig/phronomy/execution/task_result.rbs +29 -0
  484. data/sig/phronomy/extensions.rbs +0 -21
  485. data/sig/phronomy/handoff.rbs +12 -4
  486. data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
  487. data/sig/phronomy/llm_adapter/base.rbs +14 -0
  488. data/sig/phronomy/llm_adapter/usage.rbs +14 -0
  489. data/sig/phronomy/llm_adapter/values.rbs +43 -0
  490. data/sig/phronomy/llm_context_window.rbs +10 -0
  491. data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
  492. data/sig/phronomy/multi_agent/store.rbs +54 -0
  493. data/sig/phronomy/multi_agent.rbs +24 -3
  494. data/sig/phronomy/persistence/errors.rbs +18 -0
  495. data/sig/phronomy/persistence/migration.rbs +13 -0
  496. data/sig/phronomy/persistence/transaction.rbs +19 -0
  497. data/sig/phronomy/persistence.rbs +3 -185
  498. data/sig/phronomy/persistence_composition.rbs +19 -0
  499. data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
  500. data/sig/phronomy/storage/async/async_client.rbs +8 -0
  501. data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
  502. data/sig/phronomy/storage/contracts.rbs +160 -0
  503. data/sig/phronomy/tool.rbs +58 -5
  504. data/sig/phronomy/tracing/observation.rbs +7 -0
  505. data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
  506. data/sig/phronomy/vector_store/base.rbs +23 -0
  507. data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +14 -0
  508. data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
  509. data/sig/phronomy/workflow/store.rbs +8 -0
  510. data/sig/phronomy/workflow.rbs +1 -1
  511. data/sig/phronomy.rbs +0 -49
  512. metadata +462 -130
  513. data/lib/phronomy/agent/agent_invocation_session_builder.rb +0 -584
  514. data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
  515. data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
  516. data/lib/phronomy/agent/concerns/filterable.rb +0 -184
  517. data/lib/phronomy/agent/context/capability/base.rb +0 -507
  518. data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
  519. data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
  520. data/lib/phronomy/agent/context_policies/default.rb +0 -142
  521. data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
  522. data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
  523. data/lib/phronomy/agent/handoff_request.rb +0 -45
  524. data/lib/phronomy/agent/handoff_runner.rb +0 -178
  525. data/lib/phronomy/agent/phase_machine_builder.rb +0 -152
  526. data/lib/phronomy/agent/provider_call_outcome.rb +0 -106
  527. data/lib/phronomy/agent/recovery_support.rb +0 -504
  528. data/lib/phronomy/agent/selection/candidate.rb +0 -53
  529. data/lib/phronomy/agent/selection/constraint.rb +0 -49
  530. data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
  531. data/lib/phronomy/agent/tool_call_intercepted.rb +0 -29
  532. data/lib/phronomy/agent/tool_invocation_session_builder.rb +0 -276
  533. data/lib/phronomy/configuration.rb +0 -59
  534. data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
  535. data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
  536. data/lib/phronomy/generator_verifier.rb +0 -369
  537. data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
  538. data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
  539. data/lib/phronomy/metrics.rb +0 -26
  540. data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
  541. data/lib/phronomy/persistence/durable_codec.rb +0 -706
  542. data/lib/phronomy/persistence/in_memory.rb +0 -690
  543. data/lib/phronomy/persistence/repository_facades.rb +0 -535
  544. data/lib/phronomy/persistence.rb +0 -276
  545. data/lib/phronomy/recovery.rb +0 -186
  546. data/lib/phronomy/ruby_llm_patches.rb +0 -24
  547. data/lib/phronomy/runnable.rb +0 -54
  548. data/lib/phronomy/token_usage.rb +0 -85
  549. data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
  550. data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
  551. data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
  552. data/lib/phronomy/workflow_recovery.rb +0 -123
  553. data/sig/phronomy/llm_adapter.rbs +0 -11
  554. data/sig/phronomy/runtime.rbs +0 -76
  555. /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
  556. /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
  557. /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
@@ -0,0 +1,72 @@
1
+ # Entry-action names and Team task wording (R10)
2
+
3
+ ## Scope
4
+
5
+ Refactor 44 follows applied Refactor 43, core
6
+ `5c4c039273eb2324fcc9e9943ccf40bd1ffb3abd`. It changes two private action names
7
+ and two Team-generated strings. No new production class, alias, state, event,
8
+ loader rule, persistence format or public method signature is introduced.
9
+
10
+ ## Action names describe their local work
11
+
12
+ | Existing phase | Private action | Work |
13
+ |---|---|---|
14
+ | `filtering_input` | `apply_prepared_input_action` | Read `phronomy_filtered_input` from the prepared config and install it on the invocation. |
15
+ | `building_context` | `build_runtime_chat_action` | Build a Chat with the prepared projection's settings and apply its instructions, Tools and messages. |
16
+
17
+ These replace `filtering_input_action` and `building_context_action` respectively.
18
+ Their bodies, arguments, return values, exceptions and ordering are unchanged.
19
+ Input filtering and context preparation remain with the existing preparation
20
+ owners; these actions do not repeat that work. The first action keeps its unused
21
+ Agent argument so the existing bound-action construction remains unchanged.
22
+
23
+ Phase names, transition guards, callbacks and saved resume phases remain intact.
24
+ A phase is an existing lifecycle boundary; an entry-action name describes the
25
+ operation performed at that boundary. Renaming phases would require a separate
26
+ compatibility design for observation and saved executions.
27
+
28
+ ## Team tasks and completion handles
29
+
30
+ | Surface | Before | After |
31
+ |---|---|---|
32
+ | `finalize.summary` parameter description | `TaskResult summary` | `Task generation summary` |
33
+ | Newly committed `enqueue_task` result | `TaskResult #N enqueued: ...` | `Task #N enqueued: ...` |
34
+
35
+ These are observable text changes, not solely internal renames. The description
36
+ is sent to the LLM. The enqueue response is saved in Team operation metadata and
37
+ subsequently supplied as a Tool result. The task description supplied by the
38
+ caller is not rewritten. Tool names, argument names, types, optionality, task IDs,
39
+ batch ordering, queue contents and cancellation behavior are unchanged.
40
+ `Phronomy::TaskResult` continues to mean the asynchronous completion handle.
41
+ Team integration examples now use `Task A/B/C` for business-task descriptions.
42
+
43
+ The existing operation-ID deduplication returns the stored result verbatim.
44
+ Already committed legacy `TaskResult #...` results therefore remain unchanged
45
+ on replay, including after restart. This change does not migrate old records,
46
+ rewrite Journals or reformat results during readback. Reusing an operation ID
47
+ with different arguments still fails the existing identity check.
48
+
49
+ ## Verification and limits
50
+
51
+ The package checks the existing Agent transition and Chat contracts, durable
52
+ Team execution, full core/integration suites, offline examples, real SQLite,
53
+ API/SPI, types, style, gem loading and independent application. One additional
54
+ regression verifies legacy response replay after restart, no repeated writes,
55
+ the TaskResult return type and argument-identity rejection. It also passes on
56
+ the applied baseline.
57
+
58
+ Separate processes capture a committed finalize operation before its Agent
59
+ settlement and resume it using the other version, in both directions. Stored
60
+ operations remain byte-equivalent at the value level, tasks are not duplicated,
61
+ and the expected two remaining Provider calls occur. These are stubbed Provider
62
+ checks with an InMemory snapshot; they are not live-LLM or cross-version SQL tests.
63
+
64
+ The review exposed an existing [Tool schema recording gap](tool-schema-recording-gap.md)
65
+ on RubyLLM 1.16.0. R10 does not repair it or weaken definition checks. Successful
66
+ continuation here does not prove that incompatible parameter definitions are
67
+ rejected. The generated parameter description changes, while the current saved
68
+ Tool definition omits parameter details.
69
+
70
+ R09 is applied and verified. R10 is implemented and locally verified, pending
71
+ application verification. The newly discovered schema issue remains open, so
72
+ closing the original R/D inventory must not be described as absence of defects.
@@ -0,0 +1,88 @@
1
+ # Execution abstraction revision (local review candidate, 2026-09-29)
2
+
3
+ This candidate supersedes the unapplied Results split. It is based on main
4
+ 653e255a, with the earlier execution-boundary prototype included. It is not a
5
+ record of application to main. The historical D02 reports describe their original
6
+ revisions; the control ownership decision below supersedes them for this candidate.
7
+
8
+ ## Responsibilities
9
+
10
+ | Owner | Owns | Consumers should know |
11
+ |---|---|---|
12
+ | Execution Contracts (G58, B5) | Context, TaskResult/Outcome, cancellation/deadline values, shared errors, neutral scope/result implementation | Public inputs, result handles and errors |
13
+ | Execution Services (G59, B4) | Fan-out, child control lifetime, invocation admission checks, completion adaptation, worker submission and deadline registration | Start/observe APIs and domain value/error policies |
14
+ | Engine Internals (G14, B5) | Runtime resources, EventLoop, FSMSession | Only runner/lifecycle/composition owners connect here |
15
+ | Engine Concurrency (G61, B5) | Pools and queues | Engine supplies scheduling and wait-policy context |
16
+
17
+ Bands are visual organization, not a dependency order. Backend Contracts remain
18
+ in B5. `execution_contract/errors`, `execution_result` and
19
+ `execution_result/concurrency` are removed. Their neutral implementation is
20
+ integrated into the existing `execution_contract` and its `concurrency` child.
21
+ M79/M80/M81 and G60 are retired. TaskResult is not returned to Services: doing so
22
+ would recreate Engine→Services. The two contract directories remain mutually
23
+ referencing within G58; the design does not claim zero cycles or pure declarations.
24
+
25
+ ## Actual hiding, beyond renaming dependency hubs
26
+
27
+ | Consumer | Previous knowledge | Current entry point |
28
+ |---|---|---|
29
+ | Agent::ExecutionCoordinator | Extracted context scope, checked open/cancelled state, selected scope error | InvocationControls.attach + check_start!; Agent still owns admission and its result production |
30
+ | MultiAgent::Orchestrator | Called Execution's private fan-out, constructed OperationBinding, linked tokens, selected context, closed subscriptions | Execution.run_async(max_concurrency:) + start_child; supplies child invocation |
31
+ | Tools::Agent / generated subagent tools | Created deferred result and relayed completion/failure callbacks | AsyncOperation.call/capture; supplies output/error policy |
32
+ | Agent::ToolBinding | Called TaskResult.__map_completion, a special internal composition path | AsyncOperation.map; supplies filters |
33
+ | Workflow builder (earlier included change) | Used FSM's finish vocabulary | Workflow::Completion; runner translates to FSM |
34
+
35
+ InvocationControls extends the existing service helper and absorbs the removed
36
+ OperationBinding's lifetime logic. It is not a pass-through factory that still
37
+ forces callers to manage cleanup. AsyncOperation encapsulates notification
38
+ multiplicity, startup/transformation failure, and physical completion. Domain
39
+ consumers still legitimately depend on TaskResult return types and cancellation
40
+ inputs; hiding those via aliases would not improve the abstraction.
41
+
42
+ ExecutionCoordinator, WorkflowRunner and durable reconciliation coordinators
43
+ remain result producers. Their lifecycle, registry and terminal policy code has
44
+ not all been turned into a generic facade. The public user-facing async APIs and
45
+ backend contracts retain their namespaces.
46
+
47
+ ## Investigation heuristic
48
+
49
+ Detect each M0→M1, M1→M2, M0→M2 triangle in the complete Ruby + RBS graph.
50
+ Prioritize adjacent descending display bands, then other descending bands, then
51
+ all remaining graph triangles. Keep sidebar modules and visually hidden arrows.
52
+ Do not remove edges or make a triangle a CI violation solely on that basis.
53
+
54
+ For M0's direct M2 usage, inspect its actual source operation:
55
+
56
+ - Internal detail: Orchestrator linked child tokens and closed subscriptions;
57
+ Execution now owns this through start_child.
58
+ - Connection: a runner registers its session with Runtime; this can belong to
59
+ that runner. Move it only if its current owner mixes unrelated responsibilities.
60
+ - Shared/public contract: AsyncClient returns TaskResult and callers handle its
61
+ result. Keep the declared RBS dependency instead of erasing the type.
62
+
63
+ Multiple M1 paths may identify the same direct edge. Reports include both the
64
+ triangle count and the number of distinct M0→M2 pairs. RBS-only direct edges are
65
+ marked, not automatically accepted. Directory aggregation can combine different
66
+ classes/functions, so a graph path is not proof of a call chain. Dynamic dispatch
67
+ can also leak details without any constant-reference triangle.
68
+
69
+ `dependency_triangles.json` preserves all three edges' source evidence;
70
+ `dependency_triangles.csv` is the review queue. Entries start as unreviewed.
71
+ A separate narrow AST regression gate rejects the already-corrected private
72
+ scope methods and selected consumers' manual result settlement. It does not
73
+ purport to detect every possible abstraction leak.
74
+
75
+ ## Compatibility and verification scope
76
+
77
+ Execution.run/run_async accept additive max_concurrency. No new backend methods
78
+ are required from application authors. The included earlier candidate removes
79
+ InvocationContext#effective_timeout_token/#effective_cancellation_token and the
80
+ internal Deadline#attach_to, CancellationScope, old FSM vocabulary ownership.
81
+ This revision removes internal OperationBinding and TaskResult.__map_completion.
82
+ There are no backward aliases that point neutral contracts back at services.
83
+
84
+ Tests cover bounded admission, cancellation before queued start, explicit child
85
+ context identity, cleanup after completion/start failure, duplicate callback
86
+ notifications, original error identity, recovery errors, and physical completion.
87
+ Existing Agent, Tool, Workflow, persistence/recovery and async tests remain gates.
88
+ The delivered evidence report records actual execution results and limitations.
@@ -0,0 +1,28 @@
1
+ # Execution dependency ownership
2
+
3
+ Use the highest existing operation that expresses the caller's responsibility.
4
+ A facade is useful when it owns real coordination, not just because it reduces
5
+ arrows. These cases distinguish shared contracts from executable machinery.
6
+
7
+ | Caller / operation | Dependency after this change | Decision |
8
+ |---|---|---|
9
+ | ToolBinding result filter | TaskResult private completion mapping | Remove duplicate physical-completion handling; source completion alone must not finish the filtered result |
10
+ | Tracing span finish | Blocking.call_async | Generic default-pool work; observe rejection in the returned result |
11
+ | Approval listener dispatch | Blocking.call_async | Generic default-pool work; log admission and later callback errors |
12
+ | Agent/Workflow synchronous entry guard | Runtime.in_event_loop_context? | Query context without creating Runtime |
13
+ | Prompt parser, Runnable users | Execution Contracts | Public callable/value contract, not pool internals |
14
+ | Agent lifecycle/state, capability and journal input markers | Execution Contracts | Methodless classification; preserve direct include and validation |
15
+ | Tool and async-client RBS token/result references | Execution Contracts / Execution Services | Keep real public type use in the graph; do not invent a domain facade for a token |
16
+ | LLM, VectorStore, Embeddings and Storage AsyncClients | Contracts + TaskResult + Runtime/pools | Intended bridge; keep specialized submission, token and admission rules |
17
+ | Agent ExecutionCoordinator / MultiAgent binding | Concurrency operation binding | Own cancellation/deadline scope across an operation; generic Blocking is not equivalent |
18
+ | Agent and Workflow runners / execution registries | Runtime, FSM session and control delivery | Framework connection and single-writer ownership; retain these explicit dependencies |
19
+ | Engine worker pool | TaskResult and execution errors | Produces shared results; the service/Engine relationship is not acyclic |
20
+
21
+ The full dependency graph still includes references through shared error classes,
22
+ markers and RBS. Moving their source owners changes the interpretation of the
23
+ old Engine fan-in; it does not remove their actual use. The architecture gate
24
+ enforces Contracts-to-Contracts/Common only and rejects domain/backend/client
25
+ dependencies from Services or Engine. Layout is independent of those rules.
26
+
27
+ See [ADR-063](../decisions/063-execution-contracts-and-services.md) for the source
28
+ layout, behavior change and compatibility boundary.
@@ -0,0 +1,86 @@
1
+ # Shared execution metadata and value conversion
2
+
3
+ > Current boundary: r8 unit 6 supersedes the historical Chat/SDK ownership and
4
+ > adapter extension SPI below. Agent uses LLMAdapter values; the backend owns SDK
5
+ > construction/interception; Tool owns canonical schema validation. See
6
+ > `docs/architecture/r8-unit6.md` and `docs/migrations/r8-unit6.md`.
7
+
8
+
9
+ Refactor 38 addresses the remaining R03 and R11 responsibilities against core
10
+ `e7e6618493df03c2eb386d78a9303796e1e13cdc`. The candidate must be applied and
11
+ verified before those items are closed. Tool restoration itself was completed
12
+ earlier and its validation and state reconstruction remain unchanged.
13
+
14
+ ## Ownership
15
+
16
+ Ordinary dispatch creates durable facts before sending an external operation.
17
+ Recovery reads those same facts after an interruption. Their stored vocabulary
18
+ therefore belongs to the execution contract, not to a recovery procedure.
19
+
20
+ | Responsibility | Owner | Callers |
21
+ |---|---|---|
22
+ | Metadata keys/version, Tool batch capture and metadata merge | `Agent::ExecutionMetadata` in `agent/execution` | Initial/dispatch preparation, Coordinator, approval commit, recovery and MultiAgent |
23
+ | Stable Tool invocation identity | `Agent::ToolInvocation.semantic_id` | Ordinary Tool preparation and recovery subject construction |
24
+ | Ruby tree conversion before JSON serialization | `Values::Serializable.convert` in `common/values` | RuntimeRecordEncoder, RecoverySupport, ExecutionMetadata and dispatch preparation |
25
+ | Recovery descriptors and outcome interpretation | `Agent::RecoverySupport` | Recovery and the existing failure reconstruction path |
26
+
27
+ ExecutionMetadata is a stateless vocabulary and snapshot helper. It does not
28
+ start an invocation, increment revisions, open a transaction or perform recovery.
29
+ Its `with_values` preserves the old execution revision. ToolInvocation's
30
+ `semantic_id` computes the same prefixed SHA-256 value over the same four IDs
31
+ and NUL separators; it never constructs, authorizes or runs a Tool.
32
+
33
+ RecoverySupport's shared constants and snapshot/merge/identity operations are
34
+ removed, with all repository callers updated. No compatibility aliases are
35
+ added for these private implementation names. `ExecutionOutcomeCommitter`
36
+ still uses `RecoverySupport.error_from_failure` for actual failure reconstruction;
37
+ this change does not claim to remove every execution/recovery dependency.
38
+
39
+ ## Conversion contract
40
+
41
+ Serializable rebuilds Hash and Array containers, stringifies Hash keys and
42
+ Symbol values, retains scalar objects, and recursively processes `to_h` results.
43
+ It preserves input order and the previous last-value-wins behavior for keys
44
+ that become equal. It does not deep-copy String values, freeze results, reject
45
+ non-Hash `to_h` results, or catch exceptions raised by application conversion.
46
+
47
+ The unsupported-value error remains ArgumentError. Callers supply their
48
+ existing diagnostic prefix, including for errors inside nested values:
49
+
50
+ | Boundary | Exact prefix before `: <class>` |
51
+ |---|---|
52
+ | RuntimeRecordEncoder.json_value | `unsupported canonical runtime value` |
53
+ | RecoverySupport.canonical_copy and existing snapshot writers | `Recovery value is not canonically serializable` |
54
+
55
+ The two existing conversion entry points remain short adapters because they
56
+ own different error contracts. They no longer implement separate recursive
57
+ algorithms. Snapshot writers retain their historical diagnostic despite its
58
+ Recovery wording, to avoid a behavior change in this responsibility refactoring.
59
+
60
+ Serializable does not establish canonical JSON validity. CanonicalJSON still
61
+ owns numeric range, non-finite/negative-zero and encoding checks. Immutable.copy
62
+ still owns copying and freezing. ProviderCallOutcome.normalize still has its
63
+ different unsupported-value-to-String behavior. Domain codecs keep their key
64
+ validation and collision rules. These operations are intentionally not merged.
65
+
66
+ ## Compatibility and verification
67
+
68
+ Stored metadata keys, version 1, Tool identity bytes and serialized values are
69
+ unchanged. Transactions, revision checks, dispatch order, Tool restoration,
70
+ approval notifications and external-effect behavior remain with their existing
71
+ owners. Public API, signatures, raw Storage SPI and database schema are unchanged.
72
+
73
+ The conversion behavior tests run against both the applied baseline and the
74
+ candidate, including nested unsupported values and application exceptions.
75
+ Existing Tool batch tests follow their new owner; the stored identity fixture
76
+ guards compatibility. Recovery, causal durability, approval/resume and
77
+ MultiAgent tests exercise the changed callers. Full core/integration suites,
78
+ common examples, real SQLite, API/SPI snapshots, RBS, annotations and packaged
79
+ gem loading complete the candidate checks. Live PostgreSQL and live providers
80
+ are not part of this candidate's execution evidence.
81
+
82
+ This improves ownership and removes a duplicated recursive algorithm. The
83
+ dependency diagram's module and file cycles remain; their disappearance is not
84
+ the completion criterion. The applied SVG remains applied37-01 until the next
85
+ application verification. The other initial proposal groups are R06, R07,
86
+ R08/D08, R09 and R10; overall refactoring is not complete.
@@ -0,0 +1,111 @@
1
+ # GeneratorVerifier ownership and event contract
2
+
3
+ ## Role and problem
4
+
5
+ GeneratorVerifier exposes the draft/review/retry pattern. An application supplies
6
+ two Agent classes, prompt builders, optional result parsers and convergence
7
+ settings. invoke runs the Workflow and returns the existing Result, optionally
8
+ raising LowConfidenceError. Agent completion arrives as Workflow events; Workflow
9
+ entry actions return context immediately rather than awaiting Agent Tasks.
10
+
11
+ R08 and D08 describe the same issue: a 199-line build_workflow mixes the graph
12
+ with Agent startup, response parsing/normalization and failure notification.
13
+ Nested PipelineState also occupies the public facade's source file. Separating
14
+ only the file without removing receiver-to-facade private calls would leave the
15
+ responsibility problem in place.
16
+
17
+ ## Owners and reading order
18
+
19
+ | Owner | Responsibility |
20
+ |---|---|
21
+ | GeneratorVerifier | Public settings and Result; cached Workflow assembly, invocation, default JSON parser fallbacks and final confidence/raise policy. |
22
+ | GeneratorVerifier::WorkflowBuilder | Draft/review/finalize/failed graph, request IDs, prompt creation, Agent startup and convergence guard. |
23
+ | GeneratorVerifier::AgentResultReceiver | Separate draft/review payload conversion, common terminal-event classification and failure notification to the supplied Workflow. |
24
+ | GeneratorVerifier::PipelineState | Existing Workflow fields, request correlation, stale/duplicate rejection and EventLoop-owned state mutation. |
25
+
26
+ The last three constants are private. WorkflowBuilder and AgentResultReceiver
27
+ are new internal classes; PipelineState is the existing class moved with its
28
+ body and canonical name unchanged. The implementation lives in three files under
29
+ generation/generator_verifier. The public facade and Result keep their names and
30
+ locations; no loader changes or compatibility aliases are introduced.
31
+
32
+ The initial D08 sketch suggested multi_agent/generator_verifier_workflow.rb.
33
+ Since the prior layout work established generation as this pattern's owner,
34
+ the internal files now stay there instead of creating a second feature owner.
35
+ The new directory adds a module in directory-based analysis, not a public API.
36
+
37
+ WorkflowBuilder#build reads as a graph: named entries, then ordered transitions.
38
+ start_draft/start_review describe request preparation and dispatch. The receiver's
39
+ draft_payload and review_payload retain different meanings. Their common listener
40
+ has only the two internally selected phases; it is not a public configurable
41
+ pipeline. It shares the same terminal/error rules rather than combining response
42
+ formats into an options-driven generic parser.
43
+
44
+ Default parsers remain explicit callables captured by the facade. Clamp and
45
+ citation normalization move to their receiver owner. The old __send__ calls back
46
+ to facade helpers disappear. The existing private Agent event-sink entry point
47
+ is still called via send; changing that cooperation API is outside this scope.
48
+
49
+ ## Preserved ordering and failure contract
50
+
51
+ - Each Agent is constructed once, lazily during the first successful Workflow
52
+ build. The cached Workflow and Agent instances are reused. Each invoke gets a
53
+ fresh Workflow context. No locking or new concurrency policy is introduced.
54
+ - Each request gets a new UUID and a merged context before prompt construction.
55
+ The listener captures that request ID and the context's stable Workflow ID.
56
+ Workflow closures see the completed Workflow assignment before any entry runs.
57
+ - Entry actions start asynchronous Agent work and return next_state, never a
58
+ TaskResult. Inline completion remains valid because signal queues a Workflow
59
+ event. Unknown/nonterminal Agent events are ignored.
60
+ - done parses output, normalizes the phase-specific payload and signals the
61
+ matching completed event. StandardError from parsing, normalization or success
62
+ notification is signalled as the corresponding failed event with the same
63
+ exception object. Failure-notification exceptions are not retried or wrapped.
64
+ - error/timeout/cancelled use the payload error or the same phase-specific
65
+ fallback message. approval_required remains a pipeline failure. A false return
66
+ from signal is returned without a retry or a new failure event.
67
+ - PipelineState accepts only the current request ID. It clears the accepted ID,
68
+ increments iteration after draft completion, appends feedback after review,
69
+ and consumes old/duplicate results before any transition. The receiver does
70
+ not mutate context or add its own deduplication; stale done payloads can still
71
+ be parsed before the state rejects their correlated event.
72
+ - Review completes when both the lower normalized score meets threshold and
73
+ approval is literal true, or when the iteration limit has been reached.
74
+ Otherwise it returns to draft and passes the last feedback to its prompt.
75
+ - Final Result trust remains confidence >= threshold. At the iteration limit,
76
+ high confidence with approved=false can therefore still produce trusted=true.
77
+ A nonpositive limit still executes one draft/review cycle. These are observed
78
+ existing semantics, not behavior fixes hidden in this extraction.
79
+
80
+ Public initialize/invoke parameters, Result fields/trusted? alias, parser
81
+ fallbacks, score/citation normalization, error messages and PipelineState fields
82
+ remain unchanged. Agent/Workflow/Engine/Storage behavior and SQL are not modified.
83
+ Private clamp/normalize_citations implementations relocate; private overrides are
84
+ not treated as additional supported public APIs.
85
+
86
+ ## Verification and trade-off
87
+
88
+ Thirty-nine behavior examples pass unchanged on Refactor 40 and the candidate.
89
+ They cover inline completion, ignored progress, pending Task returns, both phases'
90
+ error/timeout/cancelled/approval failures, parser and notification failures,
91
+ request correlation, duplicate/old callbacks, clamping, literal approval, final
92
+ trust, iteration limits, caching, fresh state and config forwarding. Existing
93
+ delayed-callback and WebMock integration examples cover the real Workflow path.
94
+
95
+ A separate process comparison preserves public methods, parameters, constants,
96
+ Result shape, the private state name/field schema/defaults and Runtime inactivity.
97
+ Stable/Beta snapshots do not list GeneratorVerifier, so this explicit comparison
98
+ supplements those existing gates. Core/integration/examples/real SQLite, type,
99
+ style, annotations and isolated gem checks are included in distribution evidence.
100
+ Live PostgreSQL, live LLM, candidate CI and performance are not run for this scope.
101
+
102
+ The facade is 369 -> 118 lines. Workflow definition is 199 -> 34 lines, with a
103
+ 12-line facade assembly method. The three internal files are 112/89/57 lines,
104
+ for 376 total, seven more than before. Two new classes and one moved class cost
105
+ additional files; they give graph, receiver and state independent reading units.
106
+ Directory-level dependency counts increase with that physical partition; cycle
107
+ membership is unchanged. This is responsibility separation, not cycle removal.
108
+
109
+ Refactor 41 is applied and independently verified at core e87eb77f, tree
110
+ 14dc8a546a4fd96e19e0713f7480ca2efa3c331a. All nine files and the full tree match.
111
+ R08/D08 is closed. The published diagram is applied41-01. R09 and R10 remain.
@@ -20,20 +20,27 @@ returns control to the caller. Handoff changes the active Agent for the current
20
20
  coordination lifetime.
21
21
 
22
22
  Normative Handoff intent is
23
- [ADR-030](../decisions/030-agent-handoff-domain-and-durable-responsibility.md).
23
+ [ADR-030](../decisions/030-agent-handoff-domain-and-durable-responsibility.md),
24
+ with the Runner ownership amendment in
25
+ [ADR-034](../decisions/034-handoff-runner-coordination-ownership.md).
26
+
27
+ MultiAgent owns the cross-Agent turn, Handoff edges, Policy, routing and reservations.
28
+ Agent owns generic control requests, finalized Context projection and its own
29
+ execution commits. See [r8 unit 4](r8-unit4.md).
24
30
 
25
31
  ## 2. Public API
26
32
 
27
33
  ```ruby
28
- handoff = Phronomy::Agent::Handoff.new(
34
+ handoff = Phronomy::MultiAgent::Handoff.new(
29
35
  source_agent: triage,
30
36
  target_agent: billing,
31
37
  description: "Transfer billing responsibility",
32
38
  policy: policy
33
39
  )
34
40
 
35
- runner = Phronomy::Agent::HandoffRunner.new(
41
+ runner = Phronomy::MultiAgent::HandoffRunner.new(
36
42
  main_agent: triage,
43
+ persistence: stores.multi_agent,
37
44
  handoffs: [handoff]
38
45
  )
39
46
 
@@ -50,7 +57,7 @@ schemas. The generated Tool name is private transport encoding, not Handoff
50
57
  identity or public semantic contract.
51
58
 
52
59
  Phronomy intercepts the Provider Tool Call into a typed private
53
- `HandoffRequest`. It does not execute an ordinary `ToolInvocation` or emit a
60
+ `Agent::ControlRequest`. It does not execute an ordinary `ToolInvocation` or emit a
54
61
  sentinel Tool result.
55
62
 
56
63
  ## 4. Handoff Policy
@@ -0,0 +1,50 @@
1
+ # Persistence responsibility refactoring plan
2
+
3
+ The Storage staged implementation reaches its bounded S3 cleanup in Refactor 36;
4
+ application verification remains. The broader initial review still has open
5
+ proposals recorded in the remaining responsibility plan.
6
+ [ADR-033](../decisions/033-domain-persistence-ownership.md) established domain
7
+ ownership; [ADR-058](../decisions/058-neutral-storage-primitives.md) now defines
8
+ the neutral Storage SPI. Historical raw contracts are not the current API.
9
+ See the [remaining responsibility plan](remaining-refactoring-plan.md) for the
10
+ applied commit pair and the [closure review](refactoring-closure.md) for the
11
+ final naming, placement and evidence boundary.
12
+
13
+ ## Target and current ownership
14
+
15
+ Domain repositories own record meanings, codecs, revisions and business
16
+ constraints. Storage owns typed neutral resources, Records/Streams/Blobs,
17
+ conditions and transaction scopes. Concrete InMemory and SQL drivers implement
18
+ physical operations. Composition selects implementations and assembles domain
19
+ wrappers; Storage does not import concrete domain implementations.
20
+
21
+ The public `Phronomy::Persistence` facade remains the application entry point.
22
+ It is distinct from `Phronomy::Storage`, the backend extension contract.
23
+ Directories express responsibility; existing public constants need not be
24
+ renamed to match every directory. The dependency graph is not a tree.
25
+
26
+ ## Stages
27
+
28
+ | Stage | Result |
29
+ |---|---|
30
+ | 1. Domain ownership | Refactor 09 moved schemas, repositories and queries to their domains. Later layout work placed record definitions and ownership contracts beside those features. |
31
+ | 2. Neutral contract | Refactors 34 and 35 unified the failure/transaction boundaries and replaced eight raw repository slots with Resources, Records/Streams/Blobs and guarded conditions. Core, InMemory, SQLite and PostgreSQL were migrated together. Applied SPI 2 passed S2c, including real PostgreSQL. |
32
+ | 3. Naming and placement | Refactor 36 retains the facade/SPI names, feature schemas, composition and reference-driver locations. Resource owns schema-reference normalization; generic Validation does not depend on Resource. Documentation records current status and historical boundaries. Distribution application verification remains separate. |
33
+
34
+ ## Invariants and gates
35
+
36
+ All repositories and ContentStore continue to join one backend transaction.
37
+ Splitting classes must not split commits. Codec response validation stays inside
38
+ the atomic boundary. IDs, revisions, journal positions, active constraints,
39
+ record type/version/payload and the F0/F1/F4/X0 limits remain unchanged.
40
+
41
+ Product API and Storage SPI snapshots, RBS, existing domain/backend conformance,
42
+ unit/integration suites, SQL examples and isolated gem loading verify the
43
+ implemented boundary. Record which tests ran against which tree: Refactor 35's
44
+ PostgreSQL CI is evidence for Refactor 35, not a claim that unpublished
45
+ Refactor 36 ran remotely. Refactor 36 does not change SQL or its public protocol.
46
+
47
+ Keep the applied-source diagram until the delivered candidate is applied and
48
+ verified. Remaining directory cycles and runtime collaboration are recorded,
49
+ not described as eliminated by moving files. Future behavior, performance or
50
+ distributed-operation work requires its own scope and evidence.
@@ -9,8 +9,49 @@
9
9
 
10
10
  ## 1. Durable boundary
11
11
 
12
- `Phronomy::Persistence` is the single durable-state backend abstraction for
13
- stateful Agents and durable Workflows.
12
+ `Phronomy::Persistence` owns domain-neutral atomic scopes over a `Storage::Backend`.
13
+ `Agent::Store` and `MultiAgent::Store` own domain operations and result queries;
14
+ Workflow consumes its checkpoint repository directly. These roles share a
15
+ coordinator when operations must commit together. Storage implementations do not
16
+ inherit a domain service. See [r8 unit 3](r8-unit3.md) for construction and migration.
17
+
18
+ The `storage/` directory owns record carriers, portable errors, repository views,
19
+ and the Backend contract. `storage/backends/` owns physical storage implementations.
20
+ The `agent/persistence/`, `multi_agent/persistence/`, and `workflow/persistence/`
21
+ directories own their domain codecs and repositories. Agent and Team result
22
+ queries live with those domains. `storage/record_codec.rb` contains only shared
23
+ record-envelope and scalar validation; it does not select a domain schema.
24
+ `persistence_composition/` assembles the domain repositories over one raw view.
25
+ `content_store/` is a content management service over Storage, not a physical
26
+ backend family. Its Base shares text/JSON conversion with StoredContents and
27
+ the Persistence content facade. StoredContents generates content IDs, verifies
28
+ digest identity and uses the injected view's Blobs. Its StorageSchema belongs
29
+ to this service. Storage owns byte immutability, transactions and physical I/O.
30
+ The service and its schema live together; there is no `content_store/backends/`
31
+ directory or backend-selection API. See [ADR-062](../decisions/062-content-store-service.md).
32
+ Domain stores receive their record adapters from `PersistenceComposition` and
33
+ retain their observation-thread guards. The common Persistence does not select
34
+ domains, assemble repositories, or delegate domain result queries. Domain-only
35
+ record protocols bind to the exact scope when participating; there is no shared
36
+ all-domain repository facade.
37
+ See [ADR-032](../decisions/032-storage-backend-composition.md) and
38
+ [ADR-033](../decisions/033-domain-persistence-ownership.md).
39
+
40
+ `persistence/errors.rb` owns the shared domain-facing failure classes. Repository
41
+ boundaries translate four known raw Storage categories to Persistence categories,
42
+ retaining the original exception as `cause`. Upper domain state contradictions
43
+ use `Persistence::StateConflictError < Persistence::ConflictError`. Unknown and
44
+ commit-outcome-uncertain exceptions are not reclassified. Backend contracts never
45
+ depend on these upper errors. See [ADR-061](../decisions/061-persistence-failure-contracts.md)
46
+ and the [rescue-clause migration](../migrations/persistence-failure-contracts.md).
47
+
48
+ Shared value copying belongs to `Values::Immutable` in `values/`. Agent records,
49
+ Team records, Recovery classifications, and Persistence result views use this
50
+ internal helper without borrowing an Agent implementation. It copies and freezes
51
+ Hash, Array, and String trees; other values pass through unchanged. Its separate
52
+ canonical JSON check delegates to `CanonicalJSON`. Each domain codec and repository owns its record schema, key normalization,
53
+ identity, and revision validation. Moving this helper
54
+ does not change record formats, transaction ownership, or recovery guarantees.
14
55
 
15
56
  | Repository | Durable authority |
16
57
  |---|---|
@@ -18,7 +59,7 @@ stateful Agents and durable Workflows.
18
59
  | `agents` | AgentRoot |
19
60
  | `journals` | Append-only Agent journal |
20
61
  | `executions` | AgentExecution and owned child coordination |
21
- | `workflow_states` | Workflow snapshots |
62
+ | Workflow checkpoint repository | Workflow snapshots |
22
63
  | `handoff_states` | Active responsibility and exact Target reservation |
23
64
  | `teams` | TeamRoot |
24
65
  | `team_executions` | Team tasks, assignments and outcomes |
@@ -107,7 +148,7 @@ Phronomy does not claim arbitrary external exactly-once side effects.
107
148
  ## 7. Durable codec
108
149
 
109
150
  Durable backend exchange uses immutable
110
- `Phronomy::Persistence::DurableRecord` values with:
151
+ `Phronomy::Storage::DurableRecord` values with:
111
152
 
112
153
  ```text
113
154
  record_type