phronomy 0.27.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 (475) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +9 -9
  3. data/CHANGELOG.md +52 -0
  4. data/CONTRIBUTING.md +8 -8
  5. data/README.md +9 -3
  6. data/benchmark/bench_agent_invoke.rb +25 -50
  7. data/benchmark/bench_context_assembler.rb +14 -11
  8. data/benchmark/bench_regression.rb +1 -1
  9. data/benchmark/bench_tool_schema.rb +1 -1
  10. data/docs/architecture/agent-chat-and-state-ownership.md +7 -1
  11. data/docs/architecture/agent-transition-ownership.md +13 -89
  12. data/docs/architecture/backend-groups.md +152 -0
  13. data/docs/architecture/before-llm-input.md +3 -3
  14. data/docs/architecture/context-management.md +1 -1
  15. data/docs/architecture/execution-abstraction-review.md +88 -0
  16. data/docs/architecture/execution-boundaries.md +28 -0
  17. data/docs/architecture/execution-metadata-and-values.md +6 -0
  18. data/docs/architecture/multi-agent-handoff.md +6 -5
  19. data/docs/architecture/persistence.md +27 -9
  20. data/docs/architecture/r8-unit1.md +104 -0
  21. data/docs/architecture/r8-unit10.md +72 -0
  22. data/docs/architecture/r8-unit11.md +71 -0
  23. data/docs/architecture/r8-unit12.md +67 -0
  24. data/docs/architecture/r8-unit13.md +61 -0
  25. data/docs/architecture/r8-unit14.md +72 -0
  26. data/docs/architecture/r8-unit15.md +65 -0
  27. data/docs/architecture/r8-unit16.md +54 -0
  28. data/docs/architecture/r8-unit17.md +73 -0
  29. data/docs/architecture/r8-unit18.md +92 -0
  30. data/docs/architecture/r8-unit19.md +61 -0
  31. data/docs/architecture/r8-unit2.md +55 -0
  32. data/docs/architecture/r8-unit20.md +51 -0
  33. data/docs/architecture/r8-unit21.md +79 -0
  34. data/docs/architecture/r8-unit22.md +74 -0
  35. data/docs/architecture/r8-unit23.md +81 -0
  36. data/docs/architecture/r8-unit3.md +130 -0
  37. data/docs/architecture/r8-unit4.md +79 -0
  38. data/docs/architecture/r8-unit5.md +115 -0
  39. data/docs/architecture/r8-unit6.md +71 -0
  40. data/docs/architecture/r8-unit7.md +70 -0
  41. data/docs/architecture/r8-unit8.md +78 -0
  42. data/docs/architecture/r8-unit9.md +73 -0
  43. data/docs/architecture/refactoring-closure.md +10 -1
  44. data/docs/architecture/remaining-refactoring-plan.md +16 -0
  45. data/docs/architecture/storage-execution-boundaries.md +54 -0
  46. data/docs/architecture/tool-schema-recording-gap.md +6 -0
  47. data/docs/architecture/tracing.md +1 -1
  48. data/docs/architecture/workflow-terminal-ownership-design.md +2 -2
  49. data/docs/architecture.md +24 -11
  50. data/docs/decisions/015-tool-public-facade-and-rbs-boundary.md +3 -3
  51. data/docs/decisions/027-llm-adapter-provider-boundary.md +2 -0
  52. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +2 -0
  53. data/docs/decisions/031-durable-multi-agent-coordination.md +2 -0
  54. data/docs/decisions/032-storage-backend-composition.md +5 -0
  55. data/docs/decisions/034-handoff-runner-coordination-ownership.md +2 -0
  56. data/docs/decisions/035-tool-executor-capability-ownership.md +1 -1
  57. data/docs/decisions/038-responsibility-based-source-layout.md +14 -0
  58. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +8 -0
  59. data/docs/decisions/040-configuration-default-composition.md +12 -1
  60. data/docs/decisions/045-worker-input-restriction-ownership.md +4 -0
  61. data/docs/decisions/051-execution-outcome-worker-ownership.md +2 -0
  62. data/docs/decisions/056-workflow-terminal-policy-ownership.md +1 -1
  63. data/docs/decisions/058-neutral-storage-primitives.md +5 -0
  64. data/docs/decisions/059-backend-contracts-and-async-clients.md +74 -0
  65. data/docs/decisions/060-runtime-settings-and-application-configuration.md +86 -0
  66. data/docs/decisions/061-persistence-failure-contracts.md +89 -0
  67. data/docs/decisions/062-content-store-service.md +52 -0
  68. data/docs/decisions/063-execution-contracts-and-services.md +88 -0
  69. data/docs/decisions/064-agent-execution-and-multi-agent-responsibility.md +36 -0
  70. data/docs/decisions/065-vector-and-embeddings-common-operations.md +38 -0
  71. data/docs/decisions/066-llm-and-tool-operation-contracts.md +20 -0
  72. data/docs/decisions/067-agent-progress-and-engine-connection.md +29 -0
  73. data/docs/decisions/068-agent-tool-child-progress-and-tool-operation.md +36 -0
  74. data/docs/decisions/README.md +18 -1
  75. data/docs/execution-boundaries-preview.md +45 -0
  76. data/docs/features.md +8 -3
  77. data/docs/getting-started.md +9 -6
  78. data/docs/migrations/0.22.md +2 -2
  79. data/docs/migrations/durable-semantic-coordination-v2.md +2 -0
  80. data/docs/migrations/handoff-runner-multi-agent.md +2 -0
  81. data/docs/migrations/persistence-failure-contracts.md +67 -0
  82. data/docs/migrations/r8-unit10.md +36 -0
  83. data/docs/migrations/r8-unit11.md +33 -0
  84. data/docs/migrations/r8-unit12.md +31 -0
  85. data/docs/migrations/r8-unit13.md +36 -0
  86. data/docs/migrations/r8-unit14.md +31 -0
  87. data/docs/migrations/r8-unit15.md +31 -0
  88. data/docs/migrations/r8-unit16.md +26 -0
  89. data/docs/migrations/r8-unit17.md +28 -0
  90. data/docs/migrations/r8-unit18.md +29 -0
  91. data/docs/migrations/r8-unit19.md +28 -0
  92. data/docs/migrations/r8-unit20.md +24 -0
  93. data/docs/migrations/r8-unit21.md +28 -0
  94. data/docs/migrations/r8-unit22.md +29 -0
  95. data/docs/migrations/r8-unit23.md +20 -0
  96. data/docs/migrations/r8-unit4.md +67 -0
  97. data/docs/migrations/r8-unit5.md +75 -0
  98. data/docs/migrations/r8-unit6.md +109 -0
  99. data/docs/migrations/r8-unit7.md +31 -0
  100. data/docs/migrations/r8-unit8.md +33 -0
  101. data/docs/migrations/r8-unit9.md +28 -0
  102. data/docs/migrations/storage-async-client.md +103 -0
  103. data/docs/migrations/vector-async-clients.md +110 -0
  104. data/docs/persistence-backends.md +38 -21
  105. data/docs/runtime-and-concurrency.md +26 -1
  106. data/lib/phronomy/agent/admission.rb +78 -0
  107. data/lib/phronomy/agent/{lifecycle_contract/agent_already_exists_error.rb → agent_already_exists_error.rb} +1 -1
  108. data/lib/phronomy/agent/{lifecycle_contract/agent_busy_error.rb → agent_busy_error.rb} +1 -1
  109. data/lib/phronomy/agent/{lifecycle_contract/agent_purged_error.rb → agent_purged_error.rb} +1 -1
  110. data/lib/phronomy/{recovery → agent/api}/execution_rehydration_required_error.rb +1 -1
  111. data/lib/phronomy/agent/async_event_api.rb +37 -32
  112. data/lib/phronomy/agent/base.rb +74 -72
  113. data/lib/phronomy/agent/before_llm_input.rb +64 -0
  114. data/lib/phronomy/agent/composition/run_once.rb +1 -1
  115. data/lib/phronomy/agent/{context_assembly/context_candidate_resolver.rb → context_candidate_resolver.rb} +2 -2
  116. data/lib/phronomy/agent/{context_assembly/context_assembler.rb → context_preparation.rb} +35 -221
  117. data/lib/phronomy/agent/control_request.rb +21 -0
  118. data/lib/phronomy/agent/execution/agent_execution.rb +1 -1
  119. data/lib/phronomy/agent/execution/agent_invocation.rb +27 -53
  120. data/lib/phronomy/agent/execution/approval_resume_commit.rb +1 -1
  121. data/lib/phronomy/agent/execution/dispatch_preparation.rb +17 -127
  122. data/lib/phronomy/agent/execution/exact_execution.rb +44 -23
  123. data/lib/phronomy/agent/execution/execution_cancellation.rb +8 -4
  124. data/lib/phronomy/agent/execution/execution_coordinator.rb +214 -395
  125. data/lib/phronomy/agent/execution/execution_metadata.rb +1 -0
  126. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +70 -126
  127. data/lib/phronomy/agent/execution/execution_registry.rb +6 -2
  128. data/lib/phronomy/agent/execution/execution_session_runner.rb +22 -27
  129. data/lib/phronomy/agent/execution/initial_preparation.rb +18 -116
  130. data/lib/phronomy/agent/execution/{agent_invocation_session_builder.rb → invocation_actions.rb} +54 -194
  131. data/lib/phronomy/agent/execution/invocation_transitions.rb +39 -1
  132. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +7 -7
  133. data/lib/phronomy/agent/execution_change.rb +161 -0
  134. data/lib/phronomy/agent/execution_environment.rb +36 -0
  135. data/lib/phronomy/agent/execution_extension_state.rb +21 -0
  136. data/lib/phronomy/agent/execution_observation.rb +35 -0
  137. data/lib/phronomy/agent/filterable.rb +182 -0
  138. data/lib/phronomy/agent/handoff/{handoff_context.rb → transfer_context.rb} +4 -4
  139. data/lib/phronomy/agent/handoff/{handoff_projection.rb → transfer_projection.rb} +14 -33
  140. data/lib/phronomy/{llm_contract/transport_error.rb → agent/handoff_error.rb} +1 -1
  141. data/lib/phronomy/agent/journal/journal_projection.rb +1 -1
  142. data/lib/phronomy/agent/knowledge_item.rb +13 -0
  143. data/lib/phronomy/agent/lifecycle/agent_root.rb +1 -1
  144. data/lib/phronomy/agent/lifecycle/ownership_registry.rb +18 -23
  145. data/lib/phronomy/agent/persistence/agent_repository.rb +29 -21
  146. data/lib/phronomy/agent/persistence/cancellation_repository.rb +51 -0
  147. data/lib/phronomy/agent/persistence/codec.rb +1 -21
  148. data/lib/phronomy/agent/persistence/execution_repository.rb +57 -41
  149. data/lib/phronomy/agent/persistence/journal_repository.rb +27 -18
  150. data/lib/phronomy/agent/persistence/records.rb +33 -0
  151. data/lib/phronomy/agent/persistence/retention_repository.rb +70 -0
  152. data/lib/phronomy/agent/persistence/storage_schema.rb +7 -2
  153. data/lib/phronomy/agent/persistence/watermark.rb +13 -11
  154. data/lib/phronomy/agent/recovery/invocation_restorer.rb +13 -21
  155. data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +10 -9
  156. data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +27 -27
  157. data/lib/phronomy/agent/recovery/recovery_coordinator/resolution.rb +19 -21
  158. data/lib/phronomy/agent/recovery/recovery_coordinator.rb +23 -16
  159. data/lib/phronomy/agent/recovery/recovery_rules.rb +119 -0
  160. data/lib/phronomy/agent/recovery/recovery_support.rb +8 -11
  161. data/lib/phronomy/agent/reserved_execution.rb +16 -0
  162. data/lib/phronomy/agent/retention.rb +17 -0
  163. data/lib/phronomy/agent/runtime_binding/engine_environment.rb +60 -0
  164. data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +34 -0
  165. data/lib/phronomy/agent/runtime_binding/phase_machine_builder.rb +64 -0
  166. data/lib/phronomy/agent/runtime_binding/tool_session_builder.rb +34 -0
  167. data/lib/phronomy/agent/{context_assembly/ruby_llm_materializer.rb → runtime_input.rb} +18 -35
  168. data/lib/phronomy/agent/{context_assembly/saved_context_reader.rb → saved_context_reader.rb} +6 -4
  169. data/lib/phronomy/agent/settings.rb +47 -0
  170. data/lib/phronomy/agent/{context_assembly/state_writer.rb → state_writer.rb} +4 -3
  171. data/lib/phronomy/agent/store.rb +253 -0
  172. data/lib/phronomy/agent/{lifecycle_contract/stream_callback_error.rb → stream_callback_error.rb} +1 -1
  173. data/lib/phronomy/agent/tool_execution/tool_binding.rb +4 -64
  174. data/lib/phronomy/agent/tool_execution/tool_invocation.rb +50 -219
  175. data/lib/phronomy/agent/tool_execution/tool_invocation_actions.rb +107 -0
  176. data/lib/phronomy/agent/tool_execution/tool_invocation_transitions.rb +70 -0
  177. data/lib/phronomy/configuration/runtime_settings.rb +49 -0
  178. data/lib/phronomy/content_store/storage_schema.rb +1 -0
  179. data/lib/phronomy/content_store/stored_contents.rb +2 -1
  180. data/lib/phronomy/context/assembly.rb +202 -0
  181. data/lib/phronomy/{llm_contract/context_budget_exceeded_error.rb → context/budget_exceeded_error.rb} +3 -1
  182. data/lib/phronomy/context/candidate.rb +51 -0
  183. data/lib/phronomy/context/constraint.rb +47 -0
  184. data/lib/phronomy/{agent/context_contract → context}/context_plan.rb +1 -1
  185. data/lib/phronomy/{agent/context_contract → context}/context_plan_validator.rb +3 -3
  186. data/lib/phronomy/{agent/context_contract → context}/context_policy.rb +1 -1
  187. data/lib/phronomy/{agent/context_contract → context}/context_policy_input.rb +1 -1
  188. data/lib/phronomy/{agent/context_assembly → context}/context_policy_input_builder.rb +1 -1
  189. data/lib/phronomy/context/default_policy.rb +140 -0
  190. data/lib/phronomy/context/final_budget_validator.rb +33 -0
  191. data/lib/phronomy/{agent/context_contract → context}/llm_input_build_context.rb +1 -1
  192. data/lib/phronomy/{agent/context_contract → context}/llm_input_manifest.rb +19 -19
  193. data/lib/phronomy/{agent/context_contract → context}/llm_input_patch.rb +1 -1
  194. data/lib/phronomy/context/manifest_error.rb +10 -0
  195. data/lib/phronomy/context/prompt_template.rb +98 -0
  196. data/lib/phronomy/{vector_store → documents}/loader/base.rb +1 -1
  197. data/lib/phronomy/{vector_store → documents}/loader/csv_loader.rb +2 -2
  198. data/lib/phronomy/{vector_store → documents}/loader/markdown_loader.rb +3 -3
  199. data/lib/phronomy/{vector_store → documents}/loader/plain_text_loader.rb +2 -2
  200. data/lib/phronomy/{vector_store → documents}/splitter/base.rb +1 -1
  201. data/lib/phronomy/{vector_store → documents}/splitter/fixed_size_splitter.rb +2 -2
  202. data/lib/phronomy/{vector_store → documents}/splitter/recursive_splitter.rb +2 -2
  203. data/lib/phronomy/embeddings/async/async_client.rb +44 -0
  204. data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +48 -0
  205. data/lib/phronomy/embeddings/base.rb +43 -0
  206. data/lib/phronomy/embeddings/invalid_result_error.rb +11 -0
  207. data/lib/phronomy/embeddings/transport_error.rb +11 -0
  208. data/lib/phronomy/engine/concurrency/offload_pool.rb +36 -21
  209. data/lib/phronomy/engine/concurrency/pool_registry.rb +47 -12
  210. data/lib/phronomy/engine/diagnostics.rb +1 -1
  211. data/lib/phronomy/engine/event_loop.rb +7 -7
  212. data/lib/phronomy/engine/execution_binding.rb +23 -0
  213. data/lib/phronomy/engine/execution_receiver_binding.rb +43 -0
  214. data/lib/phronomy/engine/fsm_protocol.rb +1 -6
  215. data/lib/phronomy/engine/fsm_session.rb +3 -3
  216. data/lib/phronomy/engine/metrics.rb +16 -14
  217. data/lib/phronomy/engine/runtime/timer_queue.rb +1 -1
  218. data/lib/phronomy/engine/runtime.rb +25 -12
  219. data/lib/phronomy/engine/terminal_decision.rb +7 -0
  220. data/lib/phronomy/execution/async_operation.rb +41 -0
  221. data/lib/phronomy/{engine → execution}/blocking.rb +2 -2
  222. data/lib/phronomy/{engine → execution}/concurrency/cancellation_token.rb +1 -1
  223. data/lib/phronomy/{engine → execution}/concurrency/deadline.rb +0 -17
  224. data/lib/phronomy/{engine → execution}/concurrency/physical_completion_task.rb +1 -1
  225. data/lib/phronomy/{engine → execution}/concurrency/result_collector.rb +1 -1
  226. data/lib/phronomy/{engine → execution}/concurrency/result_composition.rb +33 -12
  227. data/lib/phronomy/{engine/concurrency/subscriptions.rb → execution/concurrency/result_subscriptions.rb} +14 -18
  228. data/lib/phronomy/execution/concurrency/subscriptions.rb +25 -0
  229. data/lib/phronomy/{engine → execution}/execution.rb +61 -27
  230. data/lib/phronomy/execution/execution_receiver.rb +78 -0
  231. data/lib/phronomy/execution/execution_scope_state.rb +35 -0
  232. data/lib/phronomy/{engine → execution}/invocation_context.rb +0 -15
  233. data/lib/phronomy/execution/invocation_controls.rb +73 -0
  234. data/lib/phronomy/execution/runnable.rb +24 -0
  235. data/lib/phronomy/{engine → execution}/task_result.rb +3 -3
  236. data/lib/phronomy/execution/wait_policy.rb +24 -0
  237. data/lib/phronomy/filter/{contract/filter_block_error.rb → filter_block_error.rb} +1 -1
  238. data/lib/phronomy/generation/generator_verifier/agent_operation.rb +65 -0
  239. data/lib/phronomy/generation/generator_verifier/default_parser.rb +27 -0
  240. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +2 -2
  241. data/lib/phronomy/generation/generator_verifier.rb +7 -7
  242. data/lib/phronomy/llm_adapter/async/async_client.rb +47 -0
  243. data/lib/phronomy/{llm_contract → llm_adapter}/authentication_error.rb +3 -1
  244. data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +183 -0
  245. data/lib/phronomy/llm_adapter/base.rb +49 -68
  246. data/lib/phronomy/{llm_contract → llm_adapter}/context_length_error.rb +3 -1
  247. data/lib/phronomy/llm_adapter/invalid_result_error.rb +10 -0
  248. data/lib/phronomy/llm_adapter/message.rb +62 -0
  249. data/lib/phronomy/{llm_contract → llm_adapter}/rate_limit_error.rb +3 -1
  250. data/lib/phronomy/llm_adapter/request.rb +79 -0
  251. data/lib/phronomy/llm_adapter/response.rb +36 -0
  252. data/lib/phronomy/llm_adapter/stream_chunk.rb +18 -0
  253. data/lib/phronomy/llm_adapter/token_usage.rb +64 -0
  254. data/lib/phronomy/llm_adapter/transport_error.rb +9 -0
  255. data/lib/phronomy/llm_adapter.rb +3 -16
  256. data/lib/phronomy/multi_agent/admission_registry.rb +1 -8
  257. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +108 -84
  258. data/lib/phronomy/multi_agent/execution_environment.rb +29 -0
  259. data/lib/phronomy/{agent/handoff → multi_agent}/handoff.rb +2 -2
  260. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_capability_factory.rb +21 -2
  261. data/lib/phronomy/multi_agent/handoff_participant.rb +79 -0
  262. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_policy.rb +1 -1
  263. data/lib/phronomy/multi_agent/handoff_runner.rb +77 -100
  264. data/lib/phronomy/{agent/handoff → multi_agent}/handoff_state.rb +1 -1
  265. data/lib/phronomy/multi_agent/orchestrator.rb +61 -75
  266. data/lib/phronomy/multi_agent/persistence/codec.rb +20 -0
  267. data/lib/phronomy/multi_agent/persistence/handoff_state_repository.rb +77 -0
  268. data/lib/phronomy/multi_agent/persistence/records.rb +27 -0
  269. data/lib/phronomy/multi_agent/persistence/storage_schema.rb +21 -0
  270. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +58 -42
  271. data/lib/phronomy/multi_agent/persistence/team_repository.rb +29 -21
  272. data/lib/phronomy/multi_agent/reserved_child_admission.rb +88 -0
  273. data/lib/phronomy/multi_agent/runtime_binding/engine_environment.rb +35 -0
  274. data/lib/phronomy/multi_agent/shared_state.rb +2 -2
  275. data/lib/phronomy/multi_agent/store.rb +156 -0
  276. data/lib/phronomy/multi_agent/team_coordinator.rb +83 -74
  277. data/lib/phronomy/multi_agent/team_ownership_registry.rb +2 -12
  278. data/lib/phronomy/output_parser/parse_error.rb +7 -0
  279. data/lib/phronomy/persistence/content_repository.rb +26 -0
  280. data/lib/phronomy/persistence/errors.rb +16 -0
  281. data/lib/phronomy/persistence/migration/initial_format_migration.rb +2 -2
  282. data/lib/phronomy/persistence/persistence.rb +23 -0
  283. data/lib/phronomy/persistence/save_outcome.rb +24 -0
  284. data/lib/phronomy/persistence/snapshot_comparison.rb +81 -0
  285. data/lib/phronomy/persistence/storage_boundary.rb +32 -0
  286. data/lib/phronomy/persistence/transaction.rb +86 -0
  287. data/lib/phronomy/persistence_composition/storage_schema.rb +9 -4
  288. data/lib/phronomy/persistence_composition/stores.rb +34 -0
  289. data/lib/phronomy/persistence_composition/unit4_migration.rb +276 -0
  290. data/lib/phronomy/runtime_composition/agent_defaults.rb +5 -1
  291. data/lib/phronomy/runtime_composition/configuration.rb +146 -0
  292. data/lib/phronomy/runtime_composition/evaluation_defaults.rb +7 -0
  293. data/lib/phronomy/runtime_composition/execution_defaults.rb +5 -0
  294. data/lib/phronomy/runtime_composition/generation_defaults.rb +6 -0
  295. data/lib/phronomy/runtime_composition/global_configuration.rb +38 -0
  296. data/lib/phronomy/runtime_composition/multi_agent_defaults.rb +9 -0
  297. data/lib/phronomy/runtime_composition/workflow_defaults.rb +4 -0
  298. data/lib/phronomy/storage/async/async_client.rb +60 -0
  299. data/lib/phronomy/storage/backend.rb +8 -2
  300. data/lib/phronomy/testing/eval/metrics.rb +1 -1
  301. data/lib/phronomy/testing/eval/scorer/llm_judge.rb +19 -3
  302. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +2 -2
  303. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +6 -6
  304. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +55 -52
  305. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +3 -3
  306. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +7 -7
  307. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +11 -11
  308. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +57 -51
  309. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +1 -1
  310. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +23 -22
  311. data/lib/phronomy/tool/authorization.rb +77 -0
  312. data/lib/phronomy/tool/base.rb +549 -9
  313. data/lib/phronomy/tool/call_request.rb +40 -0
  314. data/lib/phronomy/{agent/tool_execution/tool_definition_set.rb → tool/definition_set.rb} +7 -8
  315. data/lib/phronomy/tool/operation.rb +88 -0
  316. data/lib/phronomy/tool/schema.rb +214 -0
  317. data/lib/phronomy/tool/settings.rb +31 -0
  318. data/lib/phronomy/tool/tool_error.rb +7 -0
  319. data/lib/phronomy/tool/tool_executor.rb +58 -0
  320. data/lib/phronomy/tools/agent.rb +22 -90
  321. data/lib/phronomy/tools/mcp.rb +21 -14
  322. data/lib/phronomy/tools/vector_search.rb +4 -4
  323. data/lib/phronomy/tracing/automatic.rb +11 -6
  324. data/lib/phronomy/tracing/base.rb +1 -1
  325. data/lib/phronomy/tracing/observation.rb +37 -0
  326. data/lib/phronomy/tracing/settings.rb +36 -0
  327. data/lib/phronomy/vector_store/{async_backend.rb → async/async_client.rb} +35 -29
  328. data/lib/phronomy/vector_store/{in_memory.rb → backends/in_memory.rb} +12 -10
  329. data/lib/phronomy/vector_store/{pgvector.rb → backends/pgvector.rb} +44 -16
  330. data/lib/phronomy/vector_store/{redis_search.rb → backends/redis_search.rb} +74 -37
  331. data/lib/phronomy/vector_store/base.rb +118 -49
  332. data/lib/phronomy/vector_store/invalid_result_error.rb +12 -0
  333. data/lib/phronomy/vector_store.rb +2 -17
  334. data/lib/phronomy/version.rb +1 -1
  335. data/lib/phronomy/workflow/completion.rb +11 -0
  336. data/lib/phronomy/workflow/execution/workflow.rb +7 -7
  337. data/lib/phronomy/workflow/execution/workflow_action_rules.rb +67 -0
  338. data/lib/phronomy/workflow/execution/workflow_context.rb +2 -2
  339. data/lib/phronomy/workflow/execution/workflow_execution_environment.rb +27 -0
  340. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +3 -5
  341. data/lib/phronomy/workflow/execution/workflow_runner.rb +58 -79
  342. data/lib/phronomy/workflow/execution/workflow_settings.rb +28 -0
  343. data/lib/phronomy/workflow/persistence/state_repository.rb +28 -22
  344. data/lib/phronomy/workflow/persistence/storage_schema.rb +13 -0
  345. data/lib/phronomy/workflow/runtime_binding/workflow_engine_environment.rb +38 -0
  346. data/lib/phronomy/workflow/runtime_binding/workflow_phase_machine_builder.rb +156 -0
  347. data/lib/phronomy/workflow/{execution → runtime_binding}/workflow_terminal_policy.rb +4 -4
  348. data/lib/phronomy.rb +57 -16
  349. data/scripts/api_snapshot.rb +35 -15
  350. data/sig/_private/phronomy/agent/settings.rbs +19 -0
  351. data/sig/_private/phronomy/configuration/runtime_settings.rbs +20 -0
  352. data/sig/_private/phronomy/llm_adapter/async/async_client.rbs +10 -0
  353. data/sig/_private/phronomy/multi_agent/store.rbs +8 -0
  354. data/sig/_private/phronomy/persistence/storage_boundary.rbs +7 -0
  355. data/sig/_private/phronomy/tool/settings.rbs +13 -0
  356. data/sig/_private/phronomy/tracing/settings.rbs +15 -0
  357. data/sig/_private/phronomy/workflow/execution/workflow_settings.rbs +13 -0
  358. data/sig/phronomy/agent/admission.rbs +19 -0
  359. data/sig/phronomy/agent/execution_contract.rbs +132 -0
  360. data/sig/phronomy/agent/execution_environment.rbs +20 -0
  361. data/sig/phronomy/agent/store.rbs +73 -0
  362. data/sig/phronomy/agent.rbs +14 -138
  363. data/sig/phronomy/common.rbs +7 -0
  364. data/sig/phronomy/content_store/contracts.rbs +13 -0
  365. data/sig/phronomy/context.rbs +152 -0
  366. data/sig/phronomy/embeddings/async/async_client.rbs +9 -0
  367. data/sig/phronomy/embeddings/base.rbs +17 -0
  368. data/sig/phronomy/engine/concurrency/timer_bindings.rbs +22 -0
  369. data/sig/phronomy/engine/control_bindings.rbs +11 -0
  370. data/sig/phronomy/engine/control_protocols.rbs +23 -0
  371. data/sig/phronomy/engine/execution_binding.rbs +6 -0
  372. data/sig/phronomy/engine/execution_receiver.rbs +15 -0
  373. data/sig/phronomy/engine/observability.rbs +13 -0
  374. data/sig/phronomy/execution/async_operation.rbs +7 -0
  375. data/sig/phronomy/execution/blocking.rbs +5 -0
  376. data/sig/phronomy/execution/concurrency/cancellation_token.rbs +13 -0
  377. data/sig/phronomy/execution/concurrency/deadline.rbs +10 -0
  378. data/sig/phronomy/execution/concurrency/result_composition.rbs +7 -0
  379. data/sig/phronomy/execution/control_protocols.rbs +18 -0
  380. data/sig/phronomy/execution/errors.rbs +7 -0
  381. data/sig/phronomy/execution/execution.rbs +41 -0
  382. data/sig/phronomy/execution/execution_receiver.rbs +40 -0
  383. data/sig/phronomy/execution/execution_scope_state.rbs +9 -0
  384. data/sig/phronomy/execution/invocation_context.rbs +18 -0
  385. data/sig/phronomy/execution/invocation_controls.rbs +13 -0
  386. data/sig/phronomy/execution/task_result.rbs +29 -0
  387. data/sig/phronomy/extensions.rbs +0 -21
  388. data/sig/phronomy/handoff.rbs +10 -4
  389. data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +6 -0
  390. data/sig/phronomy/llm_adapter/base.rbs +14 -0
  391. data/sig/phronomy/llm_adapter/usage.rbs +14 -0
  392. data/sig/phronomy/llm_adapter/values.rbs +43 -0
  393. data/sig/phronomy/llm_context_window.rbs +10 -0
  394. data/sig/phronomy/multi_agent/reserved_child_admission.rbs +8 -0
  395. data/sig/phronomy/multi_agent/store.rbs +54 -0
  396. data/sig/phronomy/multi_agent.rbs +6 -3
  397. data/sig/phronomy/persistence/errors.rbs +18 -0
  398. data/sig/phronomy/persistence/migration.rbs +13 -0
  399. data/sig/phronomy/persistence/transaction.rbs +19 -0
  400. data/sig/phronomy/persistence.rbs +1 -99
  401. data/sig/phronomy/persistence_composition.rbs +19 -0
  402. data/sig/phronomy/runtime_composition/configuration.rbs +36 -0
  403. data/sig/phronomy/storage/async/async_client.rbs +8 -0
  404. data/sig/phronomy/storage/backends/in_memory.rbs +9 -0
  405. data/sig/phronomy/{storage.rbs → storage/contracts.rbs} +2 -16
  406. data/sig/phronomy/tool.rbs +48 -4
  407. data/sig/phronomy/tracing/observation.rbs +7 -0
  408. data/sig/phronomy/vector_store/async/async_client.rbs +13 -0
  409. data/sig/phronomy/vector_store/base.rbs +23 -0
  410. data/sig/phronomy/workflow/execution/workflow_execution_environment.rbs +14 -0
  411. data/sig/phronomy/workflow/runtime_binding/workflow_terminal_policy.rbs +7 -0
  412. data/sig/phronomy/workflow/store.rbs +8 -0
  413. data/sig/phronomy/workflow.rbs +1 -1
  414. data/sig/phronomy.rbs +0 -49
  415. metadata +318 -117
  416. data/lib/phronomy/agent/concerns/before_llm_input.rb +0 -66
  417. data/lib/phronomy/agent/concerns/error_translation.rb +0 -45
  418. data/lib/phronomy/agent/concerns/filterable.rb +0 -184
  419. data/lib/phronomy/agent/context/capability/base.rb +0 -548
  420. data/lib/phronomy/agent/context/capability/tool_executor.rb +0 -62
  421. data/lib/phronomy/agent/context/instruction/prompt_template.rb +0 -102
  422. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +0 -36
  423. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +0 -22
  424. data/lib/phronomy/agent/context_parts/validators/final_budget_validator.rb +0 -37
  425. data/lib/phronomy/agent/context_policies/default.rb +0 -142
  426. data/lib/phronomy/agent/execution/phase_machine_builder.rb +0 -101
  427. data/lib/phronomy/agent/execution/provider_call_outcome.rb +0 -106
  428. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +0 -15
  429. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +0 -131
  430. data/lib/phronomy/agent/handoff/handoff_request.rb +0 -45
  431. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +0 -7
  432. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +0 -58
  433. data/lib/phronomy/agent/persistence/queries.rb +0 -61
  434. data/lib/phronomy/agent/selection/candidate.rb +0 -53
  435. data/lib/phronomy/agent/selection/constraint.rb +0 -49
  436. data/lib/phronomy/agent/tool_execution/tool_call_intercepted.rb +0 -29
  437. data/lib/phronomy/agent/tool_execution/tool_invocation_session_builder.rb +0 -276
  438. data/lib/phronomy/configuration/configuration.rb +0 -68
  439. data/lib/phronomy/configuration/global_configuration.rb +0 -26
  440. data/lib/phronomy/engine/concurrency/cancellation_scope.rb +0 -124
  441. data/lib/phronomy/engine/concurrency/operation_binding.rb +0 -43
  442. data/lib/phronomy/engine/execution_receiver.rb +0 -65
  443. data/lib/phronomy/engine/runnable.rb +0 -54
  444. data/lib/phronomy/llm_adapter/ruby_llm.rb +0 -47
  445. data/lib/phronomy/llm_contract/token_usage.rb +0 -85
  446. data/lib/phronomy/multi_agent/persistence/queries.rb +0 -30
  447. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +0 -15
  448. data/lib/phronomy/output_parser/contract/parse_error.rb +0 -7
  449. data/lib/phronomy/persistence/api/persistence.rb +0 -140
  450. data/lib/phronomy/persistence_composition/repositories.rb +0 -77
  451. data/lib/phronomy/recovery/recovery.rb +0 -186
  452. data/lib/phronomy/tool/contract/tool_error.rb +0 -7
  453. data/lib/phronomy/vector_store/embeddings/base.rb +0 -44
  454. data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +0 -47
  455. data/lib/phronomy/workflow/phase_machine_builder.rb +0 -205
  456. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +0 -9
  457. data/sig/phronomy/execution_receiver.rbs +0 -34
  458. data/sig/phronomy/llm_adapter.rbs +0 -11
  459. data/sig/phronomy/runtime.rbs +0 -76
  460. /data/lib/phronomy/agent/{context_assembly/context_importer.rb → context_importer.rb} +0 -0
  461. /data/lib/phronomy/{engine → execution}/backpressure_error.rb +0 -0
  462. /data/lib/phronomy/{engine → execution}/cancellation_error.rb +0 -0
  463. /data/lib/phronomy/{engine → execution}/concurrency/worker_input_restricted.rb +0 -0
  464. /data/lib/phronomy/{engine → execution}/event_loop_reentrancy_error.rb +0 -0
  465. /data/lib/phronomy/{engine → execution}/execution_cancellation_error.rb +0 -0
  466. /data/lib/phronomy/{engine → execution}/execution_timeout_error.rb +0 -0
  467. /data/lib/phronomy/{engine → execution}/invalid_async_entry_action_error.rb +0 -0
  468. /data/lib/phronomy/{engine → execution}/invalid_async_transition_action_error.rb +0 -0
  469. /data/lib/phronomy/{engine → execution}/invalid_async_workflow_action_error.rb +0 -0
  470. /data/lib/phronomy/{engine → execution}/pool_shutdown_error.rb +0 -0
  471. /data/lib/phronomy/{engine → execution}/recursion_limit_error.rb +0 -0
  472. /data/lib/phronomy/{engine → execution}/runtime_shutdown_error.rb +0 -0
  473. /data/lib/phronomy/{engine → execution}/runtime_shutdown_reentrancy_error.rb +0 -0
  474. /data/lib/phronomy/{engine → execution}/scheduler_reentrancy_error.rb +0 -0
  475. /data/lib/phronomy/{engine → execution}/timeout_error.rb +0 -0
@@ -0,0 +1,55 @@
1
+ # r8 unit 2:親の予約確認とAgent受付
2
+
3
+ この単位はP02/P03の受付境界を実装する。基準はcore `16e6fcb2dd49836735598525114abfc256d0773e`。r8全体やPersistenceの全面整理の完了ではない。
4
+
5
+ ## 責務と操作
6
+
7
+ | 担当 | 公開操作・共通規則 | 依存と内部実装 |
8
+ |---|---|---|
9
+ | 共通Persistence | `atomic`、`Transaction#participate`、`committed?`。同じPersistence、同期thread、有効scope、savepoint、commit応答を検証 | Storageの公開transaction・scope規則を利用。Agent/Team/Workflowや構成担当を選ばない |
10
+ | Agent | `Admission#accept_in`。入力記録・実行ID・Agentの受付とrevision更新を同一scopeへ保存 | Agentの保存担当を使用。親のkind・Team割当・subagent snapshot・Handoff予約を解釈しない |
11
+ | MultiAgent | `ReservedChildAdmission#admit`。親の取消・slot・子IDを検証し、Agent受付を同じscopeへ参加させる | 自分の保存担当が予約の根拠を読み、必要なguardを取得する |
12
+ | 保存担当 | `Agent::Persistence::Admission`、`MultiAgent::Persistence::Reservation` | raw Storage viewはこの境界で使用。ドメイン操作へraw viewを渡さない |
13
+
14
+ AgentのRuntime admission取得、FSM開始、live状態の反映は既存のExecutionCoordinatorが引き続き所有する。新しいAdmissionはその短い保存フェーズだけであり、Agent実行全体を親のDB transactionへ入れない。通常のアプリは新しい参加クラスを実装・生成する必要がない。
15
+
16
+ `phronomy_admission` は内部の現在の配線であり、Procやオブジェクトを保存しない。永続化するのは従来の相関情報と親子IDだけ。Team/subagent/Handoffの開始・再開担当が現在の参加者を渡す。保存済み実行への再接続はExactExecutionの同一ID照合と復旧規則を維持する。
17
+
18
+ ## 保存順序と失敗
19
+
20
+ 1. Agentが既存のRuntime受付を取得し、同期workerで保存操作を開始する。
21
+ 2. MultiAgentが短い`atomic` scopeを開き、親のguardを取得してから予約を読み直す。
22
+ 3. 親の取消・割当・子の識別子を検証する。Agentは同じscopeで入力内容・AgentExecution・AgentRootを保存する。
23
+ 4. commit応答が成功した後に、Agent実行担当だけが受付結果を取得し、準備・FSM・live反映を進める。
24
+
25
+ 参加操作の戻り値はcommit成功を意味しない。`accept_in`はnilを返し、Agent内部の`result`は外側のcommitまで利用できない。二重参加、別Persistence、別thread、終了後scopeは拒否する。同じbackendを包む別Persistenceも同一scopeと扱わない。raw backend transactionの中から新しくcommit所有者を名乗ることも拒否する。
26
+
27
+ 明示的な入れ子はsavepointとして動く。内側が成功しても外側がrollbackした場合は未成立。参加処理中の例外を内側で捕捉しても、失敗したscopeの先行変更をcommitできない。LLM、Tool、scheduler、外部callback、非同期待機を参加処理へ入れない。
28
+
29
+ Storageのscope違反は`Persistence::TransactionError`へcause・backtraceを保持して変換する。この名前の変更は、保存成否が既知であるとの宣言ではない。IOError等の成否不明な保存失敗は変換・自動retryせず、既存のAgent復旧規則へ渡す。今回、一般化した保存成否照合APIは追加していない。
30
+
31
+ ## 取消との競合
32
+
33
+ TeamはTeamRoot、subagentは親AgentRoot、Handoffはrouting recordをguardとする。PostgreSQLではそのguardの行ロックと既存の条件付き更新によって、取消・変更と子受付を順序付ける。子受付側の通常readだけでは、この保証は成立しなかった。
34
+
35
+ Handoff取消側は最初に子の状態を観測し、未完了/不在ならroutingをロックして**子の状態を再取得**する。待機中に子受付がcommitした場合、古い「不在」の判断を捨て、受付済みの子へ公開取消を送る。既に終端の実行への取消は従来どおり結果参照として扱う。
36
+
37
+ InMemoryは共有Monitor、SQLiteはtransactionと書込競合検出、PostgreSQLは行ロックを使用する。SQLiteで競合したtransactionは成功とみなさず、backendの失敗を扱う。分散leaseや外部副作用のexactly-onceは追加しない。実PostgreSQLでの待機順序はexamplesの新しい3件の並行テストで確認する対象であり、InMemory/SQLiteの成功から推定して済ませない。
38
+
39
+ ## API・ファイル変更
40
+
41
+ - Agent::InitialPreparationの`build_admitted_execution`と3種の親検証・kind分岐を削除。Agent自身の受付共通処理とMultiAgentの予約判断へ分離した。
42
+ - 共通の参加frameworkを`persistence/transaction.rb`、Agent受付を`agent/admission.rb`、保存接続を既存の各domainの`persistence/`へ置いた。新しいディレクトリや独立Contractは増やしていない。
43
+ - Storage SPIに同期contextの`transaction_open?`を追加。Storage::Backendの継承実装には共通実装が提供される。継承しない独自SPI実装はこの操作も提供する必要がある。RBS・SPI snapshot・duck-typed backendの検証を更新した。
44
+ - Persistenceの既知scope失敗の公開型を`Persistence::TransactionError`へ統一し、旧Storage例外のaliasは設けない。Storageを直接使う処理では従来のStorage例外を使用する。
45
+ - RBSはsigに配置し、参加者factory、Agent受付、MultiAgentの依存を宣言する。動的な`phronomy_admission`注入も本書と利用箇所で追跡する。
46
+ - 依存解析のExecution境界規則を図のrevision表示名から分離した。unit名の更新で同期backendからExecutionへの禁止規則が解除されないことを回帰テストする。
47
+ - 保存recordの形式、ID、revision規則は変更していない。データ移行は不要。
48
+
49
+ ## 残る課題
50
+
51
+ `Persistence#transaction`とdomain repositoryの一括窓口は現行利用箇所が残るため、この単位では全面削除していない。互換維持のために新しい旧名aliasを追加したものではないが、P01/DP04の完了条件は未達である。次にdomain照会・保存構成を移し、不要な窓口を利用側と同時に削除する。
52
+
53
+ MultiAgentの保存担当にはAgentのexecution/Handoff repositoryへの参照が残る。予約検証の所有者は整理したが、親子の公開投影・認可照会・結果取込まで隠蔽したとは扱わない。P04/F02/F03の残課題として、Agentが公開する操作と、MultiAgentが所有すべき保存形式を確定する。一般的なmetadata getterを足すだけの解決にはしない。
54
+
55
+ Agent/TeamのFSM接続、Workflowのdurableな子連携(P05)、複数記録の保存成否照合(P06)、残りの配置整理、155組・393件の意味的再判定も残る。今回のSVGは実装候補を描き、全体の循環解消を示す構想図にはしない。
@@ -0,0 +1,51 @@
1
+ # R8 unit20: Passive Engine observation
2
+
3
+ ## Problem
4
+
5
+ Metrics.snapshot previously called Runtime.instance, Runtime#offload and
6
+ Runtime#event_loop. A cold snapshot constructed the default Runtime, started
7
+ default-pool workers and started the EventLoop. Looking at an existing Runtime
8
+ could initialize its other resources. The same calls rejected observation after
9
+ shutdown, precisely when diagnostics were useful. Diagnostics.snapshot and dump
10
+ inherited these effects through Metrics.snapshot.
11
+
12
+ ## Responsibility
13
+
14
+ Runtime retains ownership of its singleton and resource references. PoolRegistry
15
+ retains ownership of its default pool. Both provide internal lookup operations
16
+ using their existing mutexes, without construction or admission checks. Runtime's
17
+ existing EventLoop lookup already provides the same behavior. These lookups can
18
+ observe retained resources after shutdown without reopening them.
19
+
20
+ Metrics samples the returned resources and formats the existing ten numeric
21
+ fields. It does not inspect instance variables, decide resource initialization,
22
+ read configuration as a substitute for measurements, or cache Runtime references.
23
+ The test-only singleton lookup delegates to the internal lookup; production code
24
+ does not call a test helper. RBS describes the optional resource references.
25
+
26
+ ## Behavior and scope
27
+
28
+ Missing resources contribute zero. An uninitialized default pool therefore has
29
+ size zero even if configuration would allocate ten workers on first use. For an
30
+ existing pool, size continues to describe configured capacity, including after
31
+ shutdown; it is not a count of living workers. Named pools remain outside these
32
+ default-pool metrics. A subsequent snapshot follows the current default Runtime,
33
+ so a reset neither recreates it nor keeps stale metrics in a cache.
34
+
35
+ Counters remain independent observations. Concurrent activity or Runtime reset
36
+ can occur during a snapshot; no globally atomic observation or lifecycle barrier
37
+ is promised. Resource references are obtained under their owners' existing locks
38
+ and metrics are read after those lookup locks are released. No new lock ordering,
39
+ polling thread, subscription, observer registry or notification mechanism is added.
40
+
41
+ Unit19 pool creation and shutdown rules, cancellation, domain finalization,
42
+ shutdown deadlines and cached shutdown results are unchanged. Contract/domain
43
+ code and dependencies are unchanged. All product-code changes stay in Engine.
44
+
45
+ ## Verification
46
+
47
+ A fresh-process test exercises all three observation entry points and checks that
48
+ no Runtime or thread is created. Tests cover partial initialization, named pools,
49
+ real active/queued/abandoned worker metrics, EventLoop backlog and lag, draining,
50
+ stopping, completed and incomplete shutdown, and default Runtime replacement.
51
+ Queue barriers control concurrent boundaries without relying on chance schedules.
@@ -0,0 +1,79 @@
1
+ # r8 unit21: Tool and Tracing settings ownership
2
+
3
+ This responsibility-only refactor is based on applied unit20, commit
4
+ `bda5da03da5a4da33041953cf0eebaa32de7bb81` (tree
5
+ `dc601f86825116b34ff294200815809ee9e0ea7a`). It addresses B10 from the
6
+ Contract review. It is not a new execution feature or a unit20 regression fix.
7
+
8
+ ## Ownership
9
+
10
+ | Owner | Responsibility |
11
+ | --- | --- |
12
+ | C06 Tool | Own the default result-length value and the existing truncation rules |
13
+ | C15 Tracing | Own tracer access, the recording option and the existing observation/redaction rules |
14
+ | C05 Context | Obtain its default tracer through C15 at Assembly construction; honor explicit injection |
15
+ | Application composition | Select values and concrete tracers, expose the existing Configuration facade, bind lazy accessors |
16
+ | Neutral RuntimeSettings | Retain logger and execution resource sizes/time thresholds |
17
+
18
+ Tool::Settings contains one optional max_result_size value. Tracing::Settings
19
+ contains tracer and trace_pii. These private value containers have no settings
20
+ hierarchy, backend selection, notification service or execution resources.
21
+ Composition supplies them through lazy providers, following the existing Agent
22
+ and Workflow pattern. No Contract receives the whole application Configuration.
23
+ No new logical Contract is introduced merely because values are shared.
24
+
25
+ The public tool_result_max_size, tracer and trace_pii accessors keep their names,
26
+ defaults, writers and return values. Application choices remain application
27
+ choices. Tool truncation and Tracing redaction already belonged to their domains;
28
+ their algorithms are unchanged. Logger access remains neutral and is not moved
29
+ simply because Tracing also uses it for diagnostic messages.
30
+
31
+ This amends ADR-060's earlier grouping of tracer and recording options with
32
+ neutral runtime settings. The static graph treated that container as common;
33
+ its lack of reverse references did not prove that every field belonged there.
34
+
35
+ ## Preserve lifecycle and read positions
36
+
37
+ - Binding providers does not evaluate global configuration or start Runtime.
38
+ - Tool reads its default at the existing result-processing site, after
39
+ synchronous execution or successful asynchronous completion. An explicit
40
+ class limit keeps priority and bypasses the default read. Nil and zero retain
41
+ their existing meanings. Result transformations retain their order and count.
42
+ - Automatic tracing reads settings at span start and retains the same tracer
43
+ and recording flag in its existing handle until finish. A configuration reset
44
+ during execution does not transfer an open span to a different tracer.
45
+ - Observation keeps its existing reads before entering the application block;
46
+ it does not adopt a new snapshot policy or re-read settings after the block.
47
+ - Context::Assembly keeps its constructor-time tracer. Explicit injection,
48
+ including explicit nil, does not resolve the default provider.
49
+ - Configuration copies duplicate the value containers and preserve injected
50
+ tracer/logger identities. Nested scopes, exception restoration and reset keep
51
+ the previous behavior. A read resolves the current container without caching.
52
+
53
+ There is no change notification, polling, version counter, cache, live resource
54
+ resizing or new thread-local configuration behavior. This does not add a
55
+ guarantee of atomic reconfiguration across several independent reads.
56
+
57
+ ## Regression boundaries
58
+
59
+ Public behavior tests run unchanged on unit20 and unit21. They cover late Tool
60
+ limits for sync/cooperative/offloaded/deferred operations, transformation order
61
+ and repetition, physical completion, reset, nested scopes and tracer identity.
62
+ Tracing checks cover both recording policies, redaction, errors and open spans;
63
+ Context checks cover constructor timing and explicit injection.
64
+
65
+ Separate ownership tests inject domain values without the application facade
66
+ or neutral settings. Isolated loading verifies provider laziness and prevents
67
+ loading a concrete backend or Runtime. RBS assigns the internal declarations to
68
+ their actual owners. AST gates extend the application-configuration prohibition
69
+ to Tool, Tracing and Context, reject domain fields in neutral RuntimeSettings,
70
+ and reject direct or literal-reflective reads through its old accessors.
71
+
72
+ These are targeted regression guards. They do not prove arbitrary dynamic Ruby
73
+ dependencies. Full suite, integration, existing privacy tests, examples offline
74
+ verification and Ruby/RBS architecture analysis remain package validation gates.
75
+ The complete source/tree and validation results are recorded in the package.
76
+
77
+ Unit19/20 Engine lifecycle and passive metrics behavior remain unchanged.
78
+ F01 durable Workflow children remain separate feature work. There is no stored
79
+ data migration, public operation change or source change to examples.
@@ -0,0 +1,74 @@
1
+ # r8 unit22: MCP connection lifecycle
2
+
3
+ This change is based on applied unit21, commit
4
+ `4525e71ca808acac9eb0302a59c32f00478a7782` (tree
5
+ `957baf18c23ce5659c11454f3a89e893c07b2138`). It corrects two concrete MCP
6
+ lifecycle defects and removes an unnecessary application-composition reference.
7
+ It is not a new Contract or an Execution/Engine refactor.
8
+
9
+ ## Ownership
10
+
11
+ | Owner | Responsibility |
12
+ | --- | --- |
13
+ | MCP Tool implementation | Translate SDK cancellation and results, own the client/transport, delimit one SDK call's notification lifetime |
14
+ | Existing Execution ResultSubscriptions | Register and remove explicit-cancellation callbacks |
15
+ | Existing Execution/Engine | Admit and execute cleanup work, reject submissions after shutdown, drain accepted work |
16
+ | Neutral RuntimeSettings | Supply the currently configured common logger |
17
+
18
+ The production change is confined to `lib/phronomy/tools/mcp.rb`. Execution,
19
+ Engine, Tool Contract, runtime composition, public signatures and storage
20
+ formats are unchanged.
21
+
22
+ ## Cancellation bridge lifetime
23
+
24
+ Previously each SDK call registered a callback directly on its supplied
25
+ CancellationToken and retained it until that token was cancelled or collected.
26
+ Completed and failed calls therefore accumulated callbacks when a caller reused
27
+ a token. A later cancellation also touched obsolete MCP cancellation handles.
28
+
29
+ Each call now owns an existing ResultSubscriptions collection, registers its
30
+ bridge with explicit_cancellation, and closes the collection in ensure. This
31
+ also covers SDK errors, malformed responses and cleanup failures. Other
32
+ subscribers on the same token are preserved.
33
+
34
+ The lifetime is the concrete SDK invocation, not its caller-facing TaskResult.
35
+ If OffloadPool settles a timeout while SDK work is still running, a subsequent
36
+ explicit cancellation must still reach that work. No timer, deadline promotion,
37
+ polling thread or TaskResult completion callback is introduced by the bridge.
38
+
39
+ ResultSubscriptions.close does not revoke a callback already taken by a
40
+ concurrent cancel!. Such a callback can finish after the SDK call returns. It
41
+ only captures that call's MCP cancellation handle, whose cancellation is
42
+ idempotent; it does not look up the next client or cancel a replacement call.
43
+ This preserves the existing Execution notification semantics.
44
+
45
+ ## Cleanup rejection at Runtime shutdown
46
+
47
+ After SDK cancellation the MCP instance detaches the old client before it can
48
+ be reused. Normally its transport is closed on the named Runtime cleanup pool.
49
+ Previously the synchronous fallback handled queue saturation and a stopped
50
+ pool, but not RuntimeShutdownError raised before pool acquisition. In that
51
+ case close was skipped and the shutdown error replaced the cancellation result.
52
+
53
+ MCP now applies its existing synchronous close fallback to RuntimeShutdownError
54
+ too. It does not reopen Runtime, create another worker, retry the Tool call or
55
+ relax Engine admission. Accepted cleanup remains owned and drained by Runtime.
56
+ MCP attempts to close a rejected transport and preserves the existing best-effort
57
+ close behavior if the SDK's close itself raises.
58
+
59
+ ## Logging and validation
60
+
61
+ MCP warning output reads RuntimeSettings.current.logger once per warning and
62
+ retains the existing stderr fallback. It no longer reaches the application
63
+ Configuration facade just to obtain this common value. Logger choice is still
64
+ made by application configuration; no new setting or provider is introduced.
65
+
66
+ Focused regressions cover repeated success, SDK/response failures, explicit and
67
+ already-delivered cancellation, timeout before physical completion, cancellation
68
+ racing completion, accepted cleanup, stopped Runtime, rejected submission,
69
+ failing close and both logger paths. Concurrency tests use barriers and an
70
+ injected monotonic clock rather than timing-dependent sleeps.
71
+
72
+ These are lifecycle corrections, not merely file moves. They require no data
73
+ migration or examples source change. Deferred features, including durable
74
+ Workflow children, remain outside this change.
@@ -0,0 +1,81 @@
1
+ # r8 unit23: concrete consumer composition
2
+
3
+ This change is based on applied unit22, commit
4
+ `17cf02eb1ec0ec534b3dd8e1e64c75e13c961cfc` (tree
5
+ `dc591b3d8dfb1edace4f98e68f5e505a6c457f58`). It normalizes two concrete
6
+ composition paths identified as NC02 and NC08 in the target diagrams.
7
+ These were responsibility improvements, not demonstrated runtime failures.
8
+
9
+ ## Agent Tool
10
+
11
+ The synchronous implementation previously called the application convenience
12
+ API `Agent.run_once`, which selected an ephemeral store through
13
+ `PersistenceComposition.agent`. Its asynchronous implementation already obtained
14
+ the same default through the boot-supplied `Agent::DefaultPersistence` factory.
15
+
16
+ Both paths now obtain a fresh store from that existing factory. The synchronous
17
+ path uses public Agent creation and invocation, preserving the explicit
18
+ `context: nil`, `knowledge: []`, and `on_event: nil` creation arguments that
19
+ `run_once` supplied. It forwards the same invocation options and converts the
20
+ output to a String as before. The asynchronous implementation is unchanged.
21
+
22
+ Each call still creates its own Agent and store, even when an application-level
23
+ Agent store is configured. No Agent or store is cached. Tool definitions and
24
+ instances do not acquire persistence. Cancellation propagation, asynchronous
25
+ config token priority, Tool validation, result transforms and recovery errors
26
+ retain their existing behavior.
27
+
28
+ `Agent.run_once` remains the public application convenience API. It continues to
29
+ own explicit composition; only the concrete Tool stops depending on that facade.
30
+ Calling a public composition API is not inherently invalid. Here the narrower
31
+ existing factory lets both Tool paths follow the same ownership boundary.
32
+
33
+ ## LlmJudge
34
+
35
+ The scorer owns prompt construction, the public LLM Request, score parsing and
36
+ clamping, and its warning/raise policy. It no longer selects the configured
37
+ adapter or constructs `LLMAdapter::AsyncClient` inside `score`.
38
+
39
+ `runtime_composition/evaluation_defaults.rb` supplies a single factory during
40
+ normal application loading. The factory selects the currently configured
41
+ adapter and constructs the client. Installation creates no Configuration,
42
+ client or Runtime. It uses a private, one-time binding in the existing scorer
43
+ class, not a new Contract, module registry or application extension API.
44
+
45
+ Each score invokes the factory after prompt and Request preparation, at the
46
+ same point as the previous client construction. The adapter is therefore read
47
+ again after configuration updates, reset and scoped restoration. Neither the
48
+ adapter nor the client is cached by the scorer. The factory does not move client
49
+ construction onto a worker; the existing AsyncClient still offloads the whole
50
+ backend operation. No polling, notification, retry or scheduling mechanism is
51
+ introduced.
52
+
53
+ The constructor signature is unchanged. Subclasses inherit the same default
54
+ binding. Client construction/admission/provider failures remain within the
55
+ existing `raise_on_error` policy. Normal and eager loading remain resource-free
56
+ and do not load RSpec. The scorer can also be tested with an explicitly bound
57
+ client and its public Request dependency without loading composition or Execution.
58
+
59
+ ## Boundaries and validation
60
+
61
+ | Owner | Responsibility |
62
+ | --- | --- |
63
+ | Concrete Agent Tool | Per-call Agent creation, invocation, cancellation forwarding and output conversion |
64
+ | Existing Agent default factory | Obtain a fresh store from the supplied boot binding |
65
+ | LlmJudge | Prompt, Request, score interpretation and scoring failure policy |
66
+ | Runtime composition | Select the configured LLM adapter and build its AsyncClient |
67
+ | Existing Execution and Engine | Submission, result completion, waiting and resource ownership |
68
+
69
+ Production changes are limited to the two consumers, the new composition file
70
+ and its explicit loader wiring. Contract source, Engine, Execution, persistence
71
+ formats, RBS and public API snapshots are unchanged. Examples need no source
72
+ change. The target diagrams remain at the applied unit22 baseline until this
73
+ candidate is applied; their two concrete composition items are addressed here.
74
+
75
+ Focused tests cover fresh construction and forwarding, default binding isolation,
76
+ score-time configuration changes, scoped restoration/reset, request/client order,
77
+ worker execution, failure behavior, inheritance and resource-free boot.
78
+ The targeted AST gate prevents either consumer from reintroducing these
79
+ composition dependencies; application composition itself remains permitted to
80
+ construct the client and public convenience API. Static graphs do not certify
81
+ all dynamically injected implementations or external providers.
@@ -0,0 +1,130 @@
1
+ # r8 unit 3: Persistence ownership and Team/Agent operations
2
+
3
+ This is a candidate based on core `a82974a7fd2360a13af71831a0c3ddc75942fae3`
4
+ and examples `70b7244c9f6542062849869a7106c5a627868a80`. It implements P01 and
5
+ removes concrete adapter selection from the unit 2 admission framework. P04 is
6
+ partially implemented for Team authorization and scheduling. It is not completion
7
+ of the full contract architecture.
8
+
9
+ ## Ownership and public application construction
10
+
11
+ ```ruby
12
+ stores = Phronomy::PersistenceComposition.in_memory
13
+ # Or: PersistenceComposition.build(backend: configured_storage_backend)
14
+
15
+ Phronomy.configure do |config|
16
+ config.agent_store = stores.agent
17
+ config.team_store = stores.team
18
+ config.workflow_store = stores.workflow
19
+ end
20
+
21
+ agent = MyAgent.create(persistence: stores.agent)
22
+ team = MyTeam.create(persistence: stores.team)
23
+ workflow = Phronomy::Workflow.define(MyContext, persistence: stores.workflow) do
24
+ # Workflow definition
25
+ end
26
+
27
+ agent_result = stores.agent.result(agent_execution_id)
28
+ team_result = stores.team.result(team_execution_id)
29
+ ```
30
+
31
+ For an isolated Agent, `PersistenceComposition.agent(backend: optional_backend)`
32
+ constructs only the Agent/content components. Ordinary Agent defaults use this
33
+ factory. A composition result is a construction bundle, not a query or execution
34
+ service; pass only the relevant component to each consumer.
35
+
36
+ | Owner | Operation / responsibility |
37
+ |---|---|
38
+ | `Persistence` | `atomic`, scope validity, participation and outer commit |
39
+ | `Agent::Store` | Agent result/list/presence/authorization operations, injected Agent record protocol |
40
+ | `MultiAgent::Store` | Team result/list operations, injected Team record protocol and Agent public operations |
41
+ | Workflow checkpoint port | `load`, `save`, `delete` with instance ID and expected revision |
42
+ | Domain `persistence/` implementations | physical resource schema, records, codecs and guards |
43
+ | `PersistenceComposition` | selects backend and adapters, validates schemas and binds components |
44
+
45
+ The stores are roles inside the existing domain framework, not new independent
46
+ contracts. Logical acceptance and state-transition decisions remain in Admission,
47
+ TeamCoordinator, and the owning domain operations. Record accessors on stores are
48
+ internal protocols for their own domain, not cross-domain application APIs.
49
+ Common Persistence neither knows these types nor imports composition.
50
+
51
+ ## Atomic participation remains unchanged
52
+
53
+ The parent reservation is committed first. At child acceptance, the parent guard
54
+ is acquired before reading the current reservation, then Agent input/execution
55
+ and root revision are written in that same scope. The parent's domain owns its
56
+ reservation/cancellation/identity checks. Agent does not interpret parent schemas.
57
+ Only after the outer commit does Agent expose its accepted state and start work.
58
+
59
+ Domain adapters are injected at construction and receive the exact scope's view.
60
+ They never select another connection or commit independently. The coordinator
61
+ identity, same-thread lifetime, savepoint behavior, conflict classification,
62
+ rollback, and uncertain-commit behavior remain in force. LLM/Tool work and async
63
+ waiting remain outside these short transactions. Wrapping ordinary async invoke
64
+ in an application transaction is not a newly supported API.
65
+
66
+ ## Team uses Agent authorization, not execution metadata
67
+
68
+ `Agent::Store#authorized_operations(scope, agent_id:, execution_id:,
69
+ invocation_id:, name:, arguments:, names:)` validates the exact requested call
70
+ against one persisted execution snapshot in the caller's scope. It checks the
71
+ Agent owner, invocation identity, authorization state, name, arguments and
72
+ requested operation family. It returns immutable `AuthorizedOperation` values
73
+ with only `invocation_id`, `name`, and `arguments`, in Provider order.
74
+
75
+ Team applies these operations and owns its durable operation-result ledger.
76
+ A committed replay returns that ledger result without reapplying the batch.
77
+ `finalize` cannot overtake earlier authorized `enqueue_task` calls. A mismatch
78
+ raises `Persistence::StateConflictError` before Team's changes commit.
79
+ `Agent::Store#exist?` reports authoritative absence; failed reads still raise.
80
+
81
+ Team scheduling now uses its own retained assignment count. The default chooses
82
+ the worker with the fewest assignments, breaking ties in worker order. Custom
83
+ schedulers receive `WorkerState#assignment_count` instead of `transcript_size`.
84
+ The count is derived from existing assignments, including failures; there is no
85
+ extra mutable counter and no Agent journal read. This deliberately changes the
86
+ default balancing metric. It does not estimate tokens, duration or resource load.
87
+
88
+ ## Removed APIs and directories
89
+
90
+ - `Persistence.in_memory`, common `transaction`, `capabilities`, repository
91
+ accessors, result/list queries and Agent watermark facade methods are removed.
92
+ `Persistence.new(backend:)` constructs only the neutral coordinator.
93
+ - Domain result queries are `stores.agent.result` / `.runs` and
94
+ `stores.team.result` / `.runs`; Handoff observation remains on the Agent store
95
+ pending the ownership work below.
96
+ - `Configuration#persistence` is replaced by `agent_store`, `team_store`, and
97
+ `workflow_store`; explicit `persistence:` arguments accept the relevant port.
98
+ - The all-domain `PersistenceComposition::Repositories` and the fixed admission
99
+ adapter classes are deleted. There are no legacy API aliases.
100
+ - `persistence/api/` and the six-file `persistence/contract/` error subdivision
101
+ are removed. Shared failures are in `persistence/errors.rb`.
102
+ - Team/Workflow schema declarations are consolidated into their existing domain
103
+ `persistence/` directories; their separate `storage_contract/` directories and
104
+ root schema constants are removed.
105
+
106
+ Storage SPI 2 and physical SQL tables/indexes are unchanged. Existing Agent,
107
+ Handoff and Workflow record codecs are unchanged. New Team worker entries omit
108
+ `transcript_size`; older entries can still be decoded and the unused field is
109
+ ignored by scheduling. Assignment history remains the authority. This does not
110
+ add an API compatibility wrapper or change saved operation results.
111
+
112
+ ## Remaining work (explicitly not claimed complete)
113
+
114
+ 1. Subagent and Handoff still interpret Agent execution/routing records and
115
+ coordination data. Storage adapter class selection has been removed, but
116
+ renaming raw record access does not make it a proper public domain operation.
117
+ Resolve logical ownership, cancellation, responsibility transfer and restart
118
+ together before changing these paths; existing atomic transfer is preserved.
119
+ 2. Orchestrator's preparation/resume integration still accesses Agent-owned
120
+ execution and context details. Team's new operation projection is not a
121
+ general solution to those ownership questions.
122
+ 3. Domain-to-FSM connections, durable Workflow child protocols, multi-record
123
+ uncertain-commit evidence and the remaining semantic dependency review are
124
+ outside this implementation unit. Workflow FINISH translation already exists.
125
+ 4. PostgreSQL concurrency verification for this candidate requires the matching
126
+ core/examples branch or local PostgreSQL setup. Unit 2 CI evidence is not
127
+ evidence that this candidate has passed PostgreSQL.
128
+
129
+ The source SVG and full Ruby/RBS evidence report remaining dependencies. Visual
130
+ suppression of shared common-value arrows does not remove graph evidence.
@@ -0,0 +1,79 @@
1
+ # r8 unit 4: Agent execution and MultiAgent responsibility
2
+
3
+ Core baseline: `3c5fddcae31cc98f8e081feae9b955cf536e5834`.
4
+ Examples baseline: `0370d09fb1608b9596e1803275f713b1a204af26`.
5
+ The foundation mapping dated 2026-09-30 and its target/concept diagrams remain the
6
+ refactoring goal. This change implements the C01/C04 boundary; it does not claim
7
+ that the whole existing implementation already matches the target DAG.
8
+
9
+ | Responsibility | Owner and current entry point |
10
+ |---|---|
11
+ | Exact execution identity, admission and observation | Agent `ReservedExecution`, `start_reserved_async`, `resume_async`, `cancel_async`, `Store#observe_execution` |
12
+ | Finalized input, groups and provenance | Agent `ControlRequest`, `TransferContext`, `TransferProjection` with Context assembly |
13
+ | Selection policy, Source/Target mapping and routing | MultiAgent `HandoffPolicy`, capability binding, `HandoffRunner`, `HandoffParticipant` |
14
+ | Static subagent slot, definition, input, inherited knowledge and import progress | MultiAgent `DurableSubagentCoordinator`; immutable content snapshot |
15
+ | Execution/Root/journal mutation and publication authority | Agent `ExecutionChange` and `ExecutionOutcomeCommitter` |
16
+ | Whole-Agent retention and durable cancellation intent | Agent public operations; Agent-owned record resources |
17
+ | History removal and release of its own holds | MultiAgent `Store#forget_subagents`, `Store#forget_handoff` |
18
+ | Physical record adapters and schema | Each domain's Persistence implementation; composition assembles them |
19
+ | Offline old-format conversion | `PersistenceComposition::Unit4Migration`; examples SQL runner |
20
+
21
+ Agent interprets neither child states nor routing phases. MultiAgent uses public
22
+ Agent values and operations; it does not read AgentExecution, raw metadata,
23
+ journals, ContextImporter values or a private event-listener getter. Child results
24
+ are observed from their authoritative execution, never mirrored as mutable child
25
+ statuses in the parent snapshot. IDs for new slots are derived from canonical
26
+ parent Agent/execution/slot identity. Migration preserves existing IDs.
27
+
28
+ ## Commit participant contract
29
+
30
+ A current, synchronous participant declares a `binding` key/version and implements
31
+ `commit`, `guard_change`, and `change_evidence`. `ExecutionChange` exposes semantic
32
+ inputs only. In one outer `Persistence#atomic` scope the participant:
33
+
34
+ 1. Locks routing/Team guards where needed, then Agent roots in lexical ID order.
35
+ 2. Calls `change.prepare_in(scope)` before its own writes. This captures complete
36
+ pre-state, including cancellation intent, under those guards.
37
+ 3. Changes its own records and calls `change.commit_in(scope, state:, transfer_receipt:, pending:)` once.
38
+ 4. Returns after the outer commit. Agent publishes the captured result only then.
39
+
40
+ The change is bound to the original thread, coordinator and prepared scope. It
41
+ checks its Agent watermark and expected execution revision. A nested savepoint
42
+ cannot authorize publication. Reconciliation compares Root, execution payload,
43
+ appended journal, extension content, cancellation intent, and participant evidence
44
+ in a consistent scope. Exact post-state proves commit; exact pre-state proves no
45
+ commit; different state or failed reads require recovery. There is no write retry.
46
+ An updated record at the expected revision alone is insufficient evidence.
47
+
48
+ Subagent cancellation retains unresolved active work. Known business errors may
49
+ follow `on_error: :skip`; unknown external outcomes cannot be skipped into success.
50
+ Handoff Source transfer and Target terminal stabilization join the same Agent
51
+ change. A suspended or recovery-required Target does not stabilize routing.
52
+ Current participant key/version and Target definition must match before resuming.
53
+ Terminal results can still be read without re-creating application wiring.
54
+
55
+ ## Retention and cancellation
56
+
57
+ `agent.retentions` prevents purge independently of MultiAgent schema. C01 records
58
+ its parent/child or conversation holds when reserving/creating work. History
59
+ removal checks unfinished work, removes its references and releases only its own
60
+ owner key in the same transaction. Other holds remain authoritative.
61
+ `agent.cancellations` stores monotonic intent separately from execution revision,
62
+ so an external cancel does not invalidate an in-flight worker's captured revision.
63
+ Signal delivery follows the durable write; restored executions read that intent.
64
+
65
+ `Agent::Admission` remains the same-scope acceptance boundary. A participant never
66
+ starts a child inside a transaction or waits for its lifetime on a worker thread.
67
+ Ordinary Agent composition does not load MultiAgent routing repositories.
68
+ Standalone `dispatch_parallel` keeps its existing Runtime-scoped behavior.
69
+
70
+ ## Remaining boundaries
71
+
72
+ `MultiAgent::AdmissionRegistry` still uses Runtime shutdown coordination. Agent,
73
+ Tool and Workflow execution internals still depend on existing Engine mechanisms.
74
+ These are later r8 work, not erased by constructor injection or diagram grouping.
75
+ The measured source diagram includes those edges and cycles. PostgreSQL lock
76
+ ordering needs its actual database gate; SQLite/InMemory results do not establish
77
+ PostgreSQL behavior. The application package records executed and unexecuted gates.
78
+
79
+ See [API and saved-data migration](../migrations/r8-unit4.md).