phronomy 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +4 -0
  4. data/VERIFY.sh +27 -27
  5. data/benchmark/bench_agent_invoke.rb +26 -22
  6. data/benchmark/bench_context_assembler.rb +4 -5
  7. data/docs/architecture/agent-chat-and-state-ownership.md +147 -0
  8. data/docs/architecture/agent-configuration-and-tool-binding.md +139 -0
  9. data/docs/architecture/agent-context.md +4 -2
  10. data/docs/architecture/agent-transition-ownership.md +89 -0
  11. data/docs/architecture/before-llm-input.md +6 -0
  12. data/docs/architecture/context-management.md +30 -0
  13. data/docs/architecture/context-preparation-steps.md +90 -0
  14. data/docs/architecture/entry-action-and-team-wording.md +72 -0
  15. data/docs/architecture/execution-metadata-and-values.md +80 -0
  16. data/docs/architecture/generator-verifier-ownership.md +111 -0
  17. data/docs/architecture/multi-agent-handoff.md +8 -2
  18. data/docs/architecture/persistence-refactoring-plan.md +50 -0
  19. data/docs/architecture/persistence.md +27 -4
  20. data/docs/architecture/refactoring-closure.md +334 -0
  21. data/docs/architecture/remaining-refactoring-plan.md +374 -0
  22. data/docs/architecture/rubyllm-2-token-ownership.md +82 -0
  23. data/docs/architecture/tool-schema-recording-gap.md +50 -0
  24. data/docs/architecture/tracing.md +1 -1
  25. data/docs/architecture/workflow-terminal-ownership-design.md +104 -0
  26. data/docs/architecture.md +209 -0
  27. data/docs/decisions/014-unified-persistence-durable-state.md +11 -0
  28. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +5 -1
  29. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +13 -3
  30. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +5 -1
  31. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +5 -0
  32. data/docs/decisions/031-durable-multi-agent-coordination.md +5 -0
  33. data/docs/decisions/032-storage-backend-composition.md +80 -0
  34. data/docs/decisions/033-domain-persistence-ownership.md +79 -0
  35. data/docs/decisions/034-handoff-runner-coordination-ownership.md +76 -0
  36. data/docs/decisions/035-tool-executor-capability-ownership.md +68 -0
  37. data/docs/decisions/036-context-contract-ownership.md +86 -0
  38. data/docs/decisions/037-common-definition-ownership.md +62 -0
  39. data/docs/decisions/038-responsibility-based-source-layout.md +131 -0
  40. data/docs/decisions/039-runtime-configuration-lifecycle-ownership.md +74 -0
  41. data/docs/decisions/040-configuration-default-composition.md +94 -0
  42. data/docs/decisions/041-feature-owned-identity-registries.md +100 -0
  43. data/docs/decisions/042-feature-owned-execution-state.md +106 -0
  44. data/docs/decisions/043-storage-execution-constraint-notifications.md +75 -0
  45. data/docs/decisions/044-agent-default-and-one-shot-composition.md +106 -0
  46. data/docs/decisions/045-worker-input-restriction-ownership.md +100 -0
  47. data/docs/decisions/046-agent-responsibility-layout-and-shared-records.md +110 -0
  48. data/docs/decisions/047-recovered-execution-continuation-contract.md +116 -0
  49. data/docs/decisions/048-dispatch-preparation-worker-ownership.md +120 -0
  50. data/docs/decisions/049-initial-preparation-worker-ownership.md +111 -0
  51. data/docs/decisions/050-approval-resume-snapshot-and-commit-ownership.md +98 -0
  52. data/docs/decisions/051-execution-outcome-worker-ownership.md +151 -0
  53. data/docs/decisions/052-tool-invocation-restoration-ownership.md +92 -0
  54. data/docs/decisions/053-shared-state-coordination-ownership.md +71 -0
  55. data/docs/decisions/054-workflow-terminal-save-single-owner.md +76 -0
  56. data/docs/decisions/055-terminal-observer-failure-settlement.md +60 -0
  57. data/docs/decisions/056-workflow-terminal-policy-ownership.md +87 -0
  58. data/docs/decisions/057-storage-transaction-boundaries.md +73 -0
  59. data/docs/decisions/058-neutral-storage-primitives.md +78 -0
  60. data/docs/decisions/README.md +35 -6
  61. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +6 -0
  62. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +6 -0
  63. data/docs/features.md +9 -3
  64. data/docs/getting-started.md +4 -4
  65. data/docs/migrations/0.15.md +5 -0
  66. data/docs/migrations/durable-semantic-coordination-v2.md +6 -0
  67. data/docs/migrations/handoff-runner-multi-agent.md +35 -0
  68. data/docs/migrations/neutral-storage-spi.md +43 -0
  69. data/docs/migrations/parallel-tool-chat-removal.md +49 -0
  70. data/docs/migrations/shared-state-multi-agent.md +44 -0
  71. data/docs/migrations/storage-backend-composition.md +117 -0
  72. data/docs/migrations/storage-transaction-boundaries.md +74 -0
  73. data/docs/persistence-backends.md +162 -204
  74. data/docs/runtime-and-concurrency.md +117 -32
  75. data/lib/phronomy/agent/api/agent.rb +17 -0
  76. data/lib/phronomy/agent/async_event_api.rb +2 -2
  77. data/lib/phronomy/agent/base.rb +51 -241
  78. data/lib/phronomy/{agent.rb → agent/composition/run_once.rb} +4 -13
  79. data/lib/phronomy/agent/context/capability/base.rb +67 -26
  80. data/lib/phronomy/agent/context/capability/tool_executor.rb +62 -0
  81. data/lib/phronomy/agent/{context_assembler.rb → context_assembly/context_assembler.rb} +143 -88
  82. data/lib/phronomy/agent/{context_importer.rb → context_assembly/context_importer.rb} +2 -2
  83. data/lib/phronomy/agent/{ruby_llm_materializer.rb → context_assembly/ruby_llm_materializer.rb} +4 -7
  84. data/lib/phronomy/agent/context_assembly/runtime_chat_builder.rb +36 -0
  85. data/lib/phronomy/agent/context_assembly/saved_context_reader.rb +53 -0
  86. data/lib/phronomy/agent/context_assembly/state_writer.rb +165 -0
  87. data/lib/phronomy/agent/context_assembly/token_budget_resolver.rb +22 -0
  88. data/lib/phronomy/agent/{context_plan.rb → context_contract/context_plan.rb} +1 -1
  89. data/lib/phronomy/agent/{context_policy_input.rb → context_contract/context_policy_input.rb} +6 -6
  90. data/lib/phronomy/agent/{llm_input_build_context.rb → context_contract/llm_input_build_context.rb} +1 -1
  91. data/lib/phronomy/agent/{llm_input_manifest.rb → context_contract/llm_input_manifest.rb} +20 -20
  92. data/lib/phronomy/agent/{llm_input_patch.rb → context_contract/llm_input_patch.rb} +2 -2
  93. data/lib/phronomy/agent/{agent_execution.rb → execution/agent_execution.rb} +8 -4
  94. data/lib/phronomy/agent/{agent_invocation.rb → execution/agent_invocation.rb} +8 -13
  95. data/lib/phronomy/agent/{agent_invocation_session_builder.rb → execution/agent_invocation_session_builder.rb} +19 -95
  96. data/lib/phronomy/agent/execution/approval_resume_commit.rb +108 -0
  97. data/lib/phronomy/agent/execution/dispatch_preparation.rb +305 -0
  98. data/lib/phronomy/agent/{exact_execution.rb → execution/exact_execution.rb} +9 -10
  99. data/lib/phronomy/agent/{execution_cancellation.rb → execution/execution_cancellation.rb} +2 -3
  100. data/lib/phronomy/agent/execution/execution_coordinator.rb +1925 -0
  101. data/lib/phronomy/agent/execution/execution_failure.rb +30 -0
  102. data/lib/phronomy/agent/execution/execution_metadata.rb +53 -0
  103. data/lib/phronomy/agent/execution/execution_outcome_committer.rb +344 -0
  104. data/lib/phronomy/agent/execution/execution_registry.rb +459 -0
  105. data/lib/phronomy/agent/execution/execution_session_runner.rb +118 -0
  106. data/lib/phronomy/agent/execution/initial_preparation.rb +421 -0
  107. data/lib/phronomy/agent/execution/invocation_transitions.rb +86 -0
  108. data/lib/phronomy/agent/{phase_machine_builder.rb → execution/phase_machine_builder.rb} +20 -71
  109. data/lib/phronomy/agent/{provider_call_outcome.rb → execution/provider_call_outcome.rb} +9 -9
  110. data/lib/phronomy/agent/execution/runtime_record_encoder.rb +210 -0
  111. data/lib/phronomy/agent/{handoff_context.rb → handoff/handoff_context.rb} +2 -2
  112. data/lib/phronomy/agent/handoff/handoff_execution_coordinator.rb +15 -0
  113. data/lib/phronomy/agent/handoff/handoff_outcome_committer.rb +131 -0
  114. data/lib/phronomy/agent/{handoff_state.rb → handoff/handoff_state.rb} +1 -1
  115. data/lib/phronomy/agent/{journal_projection.rb → journal/journal_projection.rb} +4 -0
  116. data/lib/phronomy/agent/{journal_record.rb → journal/journal_record.rb} +3 -3
  117. data/lib/phronomy/agent/{llm_call_record.rb → journal/llm_call_record.rb} +2 -2
  118. data/lib/phronomy/agent/{agent_root.rb → lifecycle/agent_root.rb} +6 -2
  119. data/lib/phronomy/agent/lifecycle/default_persistence.rb +29 -0
  120. data/lib/phronomy/{engine/runtime/agent_ownership_registry.rb → agent/lifecycle/ownership_registry.rb} +24 -10
  121. data/lib/phronomy/{agent_already_exists_error.rb → agent/lifecycle_contract/agent_already_exists_error.rb} +2 -0
  122. data/lib/phronomy/{agent_busy_error.rb → agent/lifecycle_contract/agent_busy_error.rb} +2 -0
  123. data/lib/phronomy/{agent_purged_error.rb → agent/lifecycle_contract/agent_purged_error.rb} +2 -0
  124. data/lib/phronomy/agent/lifecycle_contract/handoff_error.rb +7 -0
  125. data/lib/phronomy/{stream_callback_error.rb → agent/lifecycle_contract/stream_callback_error.rb} +2 -0
  126. data/lib/phronomy/agent/persistence/agent_repository.rb +61 -0
  127. data/lib/phronomy/agent/persistence/codec.rb +358 -0
  128. data/lib/phronomy/agent/persistence/execution_repository.rb +108 -0
  129. data/lib/phronomy/agent/persistence/handoff_state_repository.rb +58 -0
  130. data/lib/phronomy/agent/persistence/journal_repository.rb +54 -0
  131. data/lib/phronomy/agent/persistence/queries.rb +61 -0
  132. data/lib/phronomy/agent/persistence/storage_schema.rb +24 -0
  133. data/lib/phronomy/agent/persistence/watermark.rb +27 -0
  134. data/lib/phronomy/agent/recovery/invocation_restorer.rb +132 -0
  135. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/continuation.rb +21 -45
  136. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/installation.rb +32 -37
  137. data/lib/phronomy/agent/{recovery_coordinator → recovery/recovery_coordinator}/resolution.rb +37 -40
  138. data/lib/phronomy/agent/{recovery_coordinator.rb → recovery/recovery_coordinator.rb} +6 -10
  139. data/lib/phronomy/agent/recovery/recovery_support.rb +227 -0
  140. data/lib/phronomy/agent/selection/candidate.rb +1 -1
  141. data/lib/phronomy/agent/{approval_evaluation_request.rb → tool_execution/approval_evaluation_request.rb} +1 -12
  142. data/lib/phronomy/agent/{tool_approval_request.rb → tool_execution/tool_approval_request.rb} +1 -10
  143. data/lib/phronomy/agent/tool_execution/tool_binding.rb +90 -0
  144. data/lib/phronomy/agent/{tool_call_intercepted.rb → tool_execution/tool_call_intercepted.rb} +2 -2
  145. data/lib/phronomy/agent/{tool_definition_set.rb → tool_execution/tool_definition_set.rb} +9 -4
  146. data/lib/phronomy/agent/{tool_invocation.rb → tool_execution/tool_invocation.rb} +69 -34
  147. data/lib/phronomy/common/configuration_error.rb +7 -0
  148. data/lib/phronomy/common/error.rb +5 -0
  149. data/lib/phronomy/{agent → common/values}/immutable.rb +9 -1
  150. data/lib/phronomy/common/values/serializable.rb +32 -0
  151. data/lib/phronomy/{configuration.rb → configuration/configuration.rb} +14 -5
  152. data/lib/phronomy/configuration/global_configuration.rb +26 -0
  153. data/lib/phronomy/content_store/storage_schema.rb +11 -0
  154. data/lib/phronomy/content_store/stored_contents.rb +43 -0
  155. data/lib/phronomy/engine/backpressure_error.rb +7 -0
  156. data/lib/phronomy/{blocking.rb → engine/blocking.rb} +1 -1
  157. data/lib/phronomy/engine/cancellation_error.rb +7 -0
  158. data/lib/phronomy/engine/concurrency/cancellation_token.rb +4 -0
  159. data/lib/phronomy/engine/concurrency/offload_pool.rb +4 -0
  160. data/lib/phronomy/engine/concurrency/operation_binding.rb +1 -1
  161. data/lib/phronomy/engine/concurrency/worker_input_restricted.rb +14 -0
  162. data/lib/phronomy/engine/event_loop.rb +158 -624
  163. data/lib/phronomy/engine/event_loop_reentrancy_error.rb +8 -0
  164. data/lib/phronomy/{execution.rb → engine/execution.rb} +0 -7
  165. data/lib/phronomy/{execution_cancellation_error.rb → engine/execution_cancellation_error.rb} +2 -0
  166. data/lib/phronomy/engine/execution_receiver.rb +65 -0
  167. data/lib/phronomy/{execution_timeout_error.rb → engine/execution_timeout_error.rb} +2 -0
  168. data/lib/phronomy/engine/fsm_protocol.rb +14 -0
  169. data/lib/phronomy/engine/fsm_session.rb +35 -28
  170. data/lib/phronomy/{invalid_async_entry_action_error.rb → engine/invalid_async_entry_action_error.rb} +2 -0
  171. data/lib/phronomy/{invalid_async_transition_action_error.rb → engine/invalid_async_transition_action_error.rb} +2 -0
  172. data/lib/phronomy/{invalid_async_workflow_action_error.rb → engine/invalid_async_workflow_action_error.rb} +2 -0
  173. data/lib/phronomy/engine/pool_shutdown_error.rb +7 -0
  174. data/lib/phronomy/engine/recursion_limit_error.rb +7 -0
  175. data/lib/phronomy/engine/runtime.rb +80 -84
  176. data/lib/phronomy/engine/runtime_shutdown_error.rb +7 -0
  177. data/lib/phronomy/engine/runtime_shutdown_reentrancy_error.rb +7 -0
  178. data/lib/phronomy/engine/scheduler_reentrancy_error.rb +9 -0
  179. data/lib/phronomy/engine/task_result.rb +4 -0
  180. data/lib/phronomy/engine/timeout_error.rb +7 -0
  181. data/lib/phronomy/filter/contract/filter_block_error.rb +14 -0
  182. data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +89 -0
  183. data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +57 -0
  184. data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +112 -0
  185. data/lib/phronomy/generation/generator_verifier.rb +118 -0
  186. data/lib/phronomy/generation/low_confidence_error.rb +14 -0
  187. data/lib/phronomy/llm_context_window/token_budget.rb +6 -7
  188. data/lib/phronomy/llm_contract/authentication_error.rb +7 -0
  189. data/lib/phronomy/{context_budget_exceeded_error.rb → llm_contract/context_budget_exceeded_error.rb} +2 -0
  190. data/lib/phronomy/llm_contract/context_length_error.rb +7 -0
  191. data/lib/phronomy/llm_contract/rate_limit_error.rb +7 -0
  192. data/lib/phronomy/{token_usage.rb → llm_contract/token_usage.rb} +2 -2
  193. data/lib/phronomy/llm_contract/transport_error.rb +7 -0
  194. data/lib/phronomy/multi_agent/admission_registry.rb +22 -2
  195. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +5 -5
  196. data/lib/phronomy/{agent → multi_agent}/handoff_runner.rb +18 -17
  197. data/lib/phronomy/multi_agent/orchestrator.rb +2 -2
  198. data/lib/phronomy/multi_agent/persistence/codec.rb +55 -0
  199. data/lib/phronomy/multi_agent/persistence/queries.rb +30 -0
  200. data/lib/phronomy/multi_agent/persistence/team_execution_repository.rb +108 -0
  201. data/lib/phronomy/multi_agent/persistence/team_repository.rb +61 -0
  202. data/lib/phronomy/{agent → multi_agent}/shared_state.rb +56 -39
  203. data/lib/phronomy/multi_agent/storage_contract/team_storage_schema.rb +15 -0
  204. data/lib/phronomy/multi_agent/team_coordinator.rb +21 -18
  205. data/lib/phronomy/multi_agent/team_execution.rb +1 -1
  206. data/lib/phronomy/{engine/runtime → multi_agent}/team_ownership_registry.rb +14 -4
  207. data/lib/phronomy/multi_agent/team_root.rb +1 -1
  208. data/lib/phronomy/output_parser/contract/parse_error.rb +7 -0
  209. data/lib/phronomy/persistence/api/persistence.rb +140 -0
  210. data/lib/phronomy/persistence/migration/initial_format_migration.rb +19 -19
  211. data/lib/phronomy/persistence_composition/repositories.rb +77 -0
  212. data/lib/phronomy/persistence_composition/storage_schema.rb +24 -0
  213. data/lib/phronomy/{execution_rehydration_required_error.rb → recovery/execution_rehydration_required_error.rb} +2 -0
  214. data/lib/phronomy/{recovery.rb → recovery/recovery.rb} +1 -1
  215. data/lib/phronomy/runtime_composition/agent_defaults.rb +7 -0
  216. data/lib/phronomy/runtime_composition/configuration_defaults.rb +9 -0
  217. data/lib/phronomy/runtime_composition/global_runtime.rb +19 -0
  218. data/lib/phronomy/storage/backend.rb +101 -0
  219. data/lib/phronomy/storage/backends/in_memory.rb +157 -0
  220. data/lib/phronomy/storage/blob_conflict_error.rb +10 -0
  221. data/lib/phronomy/storage/blobs.rb +31 -0
  222. data/lib/phronomy/storage/condition.rb +25 -0
  223. data/lib/phronomy/storage/condition_failed_error.rb +16 -0
  224. data/lib/phronomy/storage/conflict_error.rb +9 -0
  225. data/lib/phronomy/{persistence → storage}/durable_record.rb +12 -12
  226. data/lib/phronomy/storage/entry.rb +33 -0
  227. data/lib/phronomy/storage/guard_ref.rb +13 -0
  228. data/lib/phronomy/storage/not_found_error.rb +9 -0
  229. data/lib/phronomy/storage/record_codec.rb +177 -0
  230. data/lib/phronomy/storage/records.rb +61 -0
  231. data/lib/phronomy/storage/resource.rb +126 -0
  232. data/lib/phronomy/storage/scope.rb +25 -0
  233. data/lib/phronomy/storage/serialization_error.rb +9 -0
  234. data/lib/phronomy/storage/streams.rb +44 -0
  235. data/lib/phronomy/storage/transaction_error.rb +10 -0
  236. data/lib/phronomy/storage/unique_constraint_error.rb +17 -0
  237. data/lib/phronomy/storage/unsupported_backend_error.rb +9 -0
  238. data/lib/phronomy/storage/validation.rb +53 -0
  239. data/lib/phronomy/storage/view.rb +131 -0
  240. data/lib/phronomy/testing/persistence_contract/a_content_store.rb +1 -1
  241. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +4 -4
  242. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +10 -7
  243. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +2 -2
  244. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +6 -6
  245. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +6 -6
  246. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +8 -8
  247. data/lib/phronomy/testing/persistence_contract/neutral_storage_primitives.rb +263 -0
  248. data/lib/phronomy/testing/persistence_contract/storage_transaction_boundaries.rb +123 -0
  249. data/lib/phronomy/testing/persistence_contract.rb +4 -0
  250. data/lib/phronomy/tool/contract/tool_error.rb +7 -0
  251. data/lib/phronomy/tools/agent.rb +1 -1
  252. data/lib/phronomy/version.rb +1 -1
  253. data/lib/phronomy/{workflow.rb → workflow/execution/workflow.rb} +8 -6
  254. data/lib/phronomy/{workflow_context.rb → workflow/execution/workflow_context.rb} +4 -0
  255. data/lib/phronomy/workflow/execution/workflow_context_ownership_error.rb +7 -0
  256. data/lib/phronomy/workflow/execution/workflow_execution_registry.rb +188 -0
  257. data/lib/phronomy/{workflow_runner.rb → workflow/execution/workflow_runner.rb} +122 -71
  258. data/lib/phronomy/workflow/execution/workflow_terminal_policy.rb +40 -0
  259. data/lib/phronomy/workflow/persistence/codec.rb +153 -0
  260. data/lib/phronomy/workflow/persistence/state_repository.rb +57 -0
  261. data/lib/phronomy/workflow/phase_machine_builder.rb +2 -2
  262. data/lib/phronomy/workflow/storage_contract/workflow_storage_schema.rb +9 -0
  263. data/lib/phronomy.rb +52 -94
  264. data/scripts/api_snapshot.rb +1 -1
  265. data/scripts/storage_spi_snapshot.rb +36 -0
  266. data/sig/phronomy/agent.rbs +0 -1
  267. data/sig/phronomy/execution_receiver.rbs +34 -0
  268. data/sig/phronomy/handoff.rbs +4 -2
  269. data/sig/phronomy/multi_agent.rbs +18 -0
  270. data/sig/phronomy/persistence.rbs +7 -91
  271. data/sig/phronomy/storage.rbs +174 -0
  272. data/sig/phronomy/tool.rbs +10 -1
  273. metadata +230 -99
  274. data/lib/phronomy/agent/execution_coordinator.rb +0 -3151
  275. data/lib/phronomy/agent/handoff_execution_coordinator.rb +0 -143
  276. data/lib/phronomy/agent/recovery_support.rb +0 -504
  277. data/lib/phronomy/agent/token_budget_resolver.rb +0 -70
  278. data/lib/phronomy/agent/tool_executor.rb +0 -55
  279. data/lib/phronomy/generator_verifier.rb +0 -369
  280. data/lib/phronomy/invalid_context_budget_configuration_error.rb +0 -8
  281. data/lib/phronomy/multi_agent/parallel_tool_chat.rb +0 -116
  282. data/lib/phronomy/persistence/durable_codec.rb +0 -706
  283. data/lib/phronomy/persistence/in_memory.rb +0 -690
  284. data/lib/phronomy/persistence/repository_facades.rb +0 -535
  285. data/lib/phronomy/persistence.rb +0 -276
  286. data/lib/phronomy/ruby_llm_patches.rb +0 -24
  287. data/lib/phronomy/workflow_recovery.rb +0 -123
  288. /data/lib/phronomy/agent/{context_candidate_resolver.rb → context_assembly/context_candidate_resolver.rb} +0 -0
  289. /data/lib/phronomy/agent/{context_policy_input_builder.rb → context_assembly/context_policy_input_builder.rb} +0 -0
  290. /data/lib/phronomy/agent/{context_plan_validator.rb → context_contract/context_plan_validator.rb} +0 -0
  291. /data/lib/phronomy/agent/{context_policy.rb → context_contract/context_policy.rb} +0 -0
  292. /data/lib/phronomy/agent/{llm_operation_result.rb → execution/llm_operation_result.rb} +0 -0
  293. /data/lib/phronomy/agent/{handoff.rb → handoff/handoff.rb} +0 -0
  294. /data/lib/phronomy/agent/{handoff_capability_factory.rb → handoff/handoff_capability_factory.rb} +0 -0
  295. /data/lib/phronomy/agent/{handoff_policy.rb → handoff/handoff_policy.rb} +0 -0
  296. /data/lib/phronomy/agent/{handoff_projection.rb → handoff/handoff_projection.rb} +0 -0
  297. /data/lib/phronomy/agent/{handoff_request.rb → handoff/handoff_request.rb} +0 -0
  298. /data/lib/phronomy/agent/{tool_invocation_session_builder.rb → tool_execution/tool_invocation_session_builder.rb} +0 -0
  299. /data/lib/phronomy/{canonical_json.rb → common/canonical_json.rb} +0 -0
  300. /data/lib/phronomy/{diagnostics.rb → engine/diagnostics.rb} +0 -0
  301. /data/lib/phronomy/{event.rb → engine/event.rb} +0 -0
  302. /data/lib/phronomy/{invocation_context.rb → engine/invocation_context.rb} +0 -0
  303. /data/lib/phronomy/{metrics.rb → engine/metrics.rb} +0 -0
  304. /data/lib/phronomy/{runnable.rb → engine/runnable.rb} +0 -0
@@ -0,0 +1,374 @@
1
+ # Remaining responsibility refactoring
2
+
3
+ This tracks responsibility work, remaining proposals and acceptance gates; it does
4
+ not define a new Storage SPI or Workflow lifecycle contract. The historical
5
+ inventory baseline was core `e4ad9948798a4f165d052bd8ab5ac3574cf48e24`
6
+ and examples `2f8b467f1268dd21de4c02b1c90c8bdd211d1feb` on `refactor/architecture`.
7
+
8
+ W1 is now verified at core `42f61514929645662e16b571afff9f4060d867d1`.
9
+ W2a is applied and verified at core `01cd2f57549f6d1e60825254f4520d0f123e651c`.
10
+ W2b is applied and verified at core `fcd434c45ad98e5c93953cbce1ffef3c12246894`. See the
11
+ [W2 design review](workflow-terminal-ownership-design.md) and
12
+ [ADR-056](../decisions/056-workflow-terminal-policy-ownership.md).
13
+
14
+ The current applied baseline is core
15
+ `5c4c039273eb2324fcc9e9943ccf40bd1ffb3abd` and examples
16
+ `68a0bbd0e354b9e00bbfed728ad2b769b389ed8a` (Refactor 43; examples unchanged).
17
+ S2b/S2c were verified on Refactor 35, including PostgreSQL CI against its
18
+ core ebd99623 / examples 68a0bbd0 pair.
19
+ Refactor 36's S3, Refactor 37's D02, Refactor 38's R03/R11, Refactor 39's R06
20
+ and Refactor 40's R07 are applied and verified, as is Refactor 41's R08/D08.
21
+ The diagram is on applied43-01. Refactor 42 Tool binding and current DSL
22
+ contracts and Refactor 43 Chat/state ownership are applied and verified; R09
23
+ is closed. Refactor 44 implements R10, pending application verification. The
24
+ new Tool schema recording finding remains open. See the
25
+ [closure review](refactoring-closure.md) for retained names, evidence and limits.
26
+
27
+ ## Completed boundaries
28
+
29
+ ExecutionCoordinator's staged split, ToolInvocation restoration ownership and
30
+ SharedState's MultiAgent ownership are complete. Domain codecs/repositories
31
+ already belong to Agent, MultiAgent and Workflow (ADR-033). Raw storage conflicts
32
+ already use Storage-owned exceptions (ADR-043). `FSMProtocol::FINISH` already
33
+ owns the common terminal marker; that earlier constant dependency is not the
34
+ remaining Workflow problem.
35
+
36
+ ## Execution order and completion gates
37
+
38
+ | Step | Remaining concern | Scope and completion gate |
39
+ |---|---|---|
40
+ | W1: Refactor 31 | Two terminal-save implementations, selected by prepend | Applied and verified. The active F1-aware implementation belongs to Runner and the override is removed. See [ADR-054](../decisions/054-workflow-terminal-save-single-owner.md). |
41
+ | W2a: Refactor 32 | Terminal observer exceptions leave stream and admission pending | Keep the error path open through notification, preserve the original exception and any confirmed save, and verify application before ownership extraction. See [ADR-055](../decisions/055-terminal-observer-failure-settlement.md). Applied and verified at 01cd2f57. |
42
+ | W2b: Workflow terminal ownership | FSMSession interprets `workflow_terminal_persistence_result` and success/known-failure/unknown outcomes | Applied and verified in Refactor 33 at fcd434c4; WorkflowTerminalPolicy and FSMProtocol::TerminalDecision own the boundary. Preserve session identity, event acceptance, stream barriers, admission retention/release and Task ordering. Do not simply hide the same Workflow policy behind renamed Engine methods. |
43
+ | S1: Storage contract design | Eight fixed repository slots and Agent watermark are in the shared contract | Design completed: Records/Streams/Blobs with conditions and guarded checks. The existing 37 raw methods have been inventoried; S2b now implements that design. |
44
+ | S2a: Refactor 34 | Existing update, batch validation and nested transaction differences | Applied and verified at core ac07b6d4 / examples ae538996, including PostgreSQL 17.11 on Ruby 3.2/3.3/3.4. See ADR-057. |
45
+ | S2b: Neutral Storage SPI | Common/domain contracts and all backends must agree | Applied and verified at ebd99623 / 68a0bbd0: Records/Streams/Blobs, feature schemas/adapters, failed-view lifecycle and non-local-exit rollback. See ADR-058. |
46
+ | S2c: Integration and migration | Physical backends must satisfy the same contract | Completed for Refactor 35. PostgreSQL 17.11 on Ruby 3.2/3.3/3.4: 119 examples per version; SQLite: 116. All 13 CI jobs checked out the verified core/examples pair. API/RBS, gem, round-trip data compatibility and applied trees were verified. |
47
+ | S3: Naming and closure | Common framework naming and public Persistence facade can be conflated | Reviewed and implemented in Refactor 36: retain public Persistence, neutral Storage, feature schemas and separate composition; move resource-reference normalization from generic Validation to Resource. Update stale status documents. Applied and verified at d98822b3; do not rename merely to simplify a diagram. |
48
+
49
+ W1 precedes W2 so the active terminal save is explicit before its session-facing
50
+ ownership changes. W2 can be completed without redesigning Storage's raw SPI.
51
+ Storage follows because its common contract affects all domain repositories and
52
+ both SQL reference implementations. Verify the applied commit before producing
53
+ the next dependent source package.
54
+
55
+ ## W2 implemented boundary
56
+
57
+ Runner retains snapshot capture, Offload submission, one save and F1 readback.
58
+ WorkflowTerminalPolicy recognizes the Workflow result event and interprets its
59
+ outcomes. FSMSession receives only complete/fail/retire decisions and owns its
60
+ pending state; Registry remains the sole Workflow admission owner.
61
+
62
+ The private terminal_policy injection replaces terminal_barrier, without a
63
+ public plugin API or alias. Agent/Tool and ephemeral Workflow keep immediate
64
+ completion. Unknown outcomes retain admission and an unresolved caller until
65
+ normal shutdown clears admission; shutdown does not synthesize a caller result.
66
+ Refactor 32's observer-error ordering and committed snapshot are preserved.
67
+
68
+ The candidate tests delayed success, known failures, F1 reconciliation,
69
+ uncertainty/shutdown, early/duplicate/late events, ordinary events during the
70
+ barrier, observer errors, rejected submission/delivery and shared Agent/Tool
71
+ behavior. Its application verification is complete; Storage S1 design followed.
72
+
73
+ ## S1 baseline operation inventory (before SPI 2)
74
+
75
+ Removing Agent/Workflow constant references did not make the SPI domain-neutral.
76
+ `Storage::Backend < Storage::Repositories` constructed eight required slots;
77
+ `assert_agent_watermark!` checks Agent revision and Journal position together.
78
+
79
+ | Current area | Existing constraint to preserve | Ownership/design question |
80
+ |---|---|---|
81
+ | Contents | Canonical content identity and reads/writes join the same transaction | Keep the content contract without coupling it to an execution owner. |
82
+ | Agents / Teams | Key identity and expected/next revision CAS | Separate physical compare-and-write from domain record validation. |
83
+ | Journals | Expected head position, append order and record identity | Preserve atomic append; a generic key/value write alone is insufficient. |
84
+ | Agent / Team executions | Atomic active-owner exclusion, immutable owner identity, revision checks and indexed queries | Decide a neutral constraint/index primitive or explicit domain-owned extension; never replace atomic admission with an unlocked preflight. |
85
+ | Workflow / Handoff states | Create/update/delete CAS and stored identity | Preserve nil pre-revision creation and conditional deletion, with domain interpretation above the raw contract. |
86
+ | Agent watermark | Revision and Journal head observed consistently with subsequent writes | Express a multi-record precondition or domain-owned transaction operation, not independent reads above the backend. |
87
+ | Transaction view | All eight repositories, content and watermark share one view | Keep InMemory's one Monitor/snapshot and each SQL view's one checked-out connection; splitting classes must not split commits. |
88
+ | Errors / capability declarations | Dedicated active constraint errors, ordinary conflicts and uncertainty remain distinct | Revisit domain terms in capabilities without adding stronger concurrency or commit-certainty promises. |
89
+
90
+ Reference implementations live in `storage/backends/in_memory.rb` and examples
91
+ `30_sqlite_persistence` / `31_postgresql_persistence`. Inspect SQL indexes, lock
92
+ order, connection binding and rollback as well as Ruby signatures. Storage's
93
+ existing Agent/Team implementations have different details; do not assume they
94
+ are interchangeable just because their method names resemble each other.
95
+
96
+ S1 must produce a mapping from every current operation to its owner and atomic
97
+ primitive, plus API/RBS migration and backend conformance gates. Do not adopt a
98
+ generic key/value API, callbacks inside transactions or a registry of arbitrary
99
+ operations merely to erase domain names. Keep record type/version/payload,
100
+ existing F0/F1/F4 limits and the X0 external-effect boundary explicit.
101
+
102
+ See the existing [persistence staged plan](persistence-refactoring-plan.md),
103
+ [ADR-033](../decisions/033-domain-persistence-ownership.md) and
104
+ [ADR-043](../decisions/043-storage-execution-constraint-notifications.md).
105
+
106
+ ## S2a and S2b applied boundaries
107
+
108
+ [ADR-057](../decisions/057-storage-transaction-boundaries.md) records the three
109
+ behavioral changes. The [migration guide](../migrations/storage-transaction-boundaries.md)
110
+ explains nested savepoints and propagated ActiveRecord::Rollback. Complete batch
111
+ validation prevents invalid input from leaving partial Journal rows; it does not
112
+ make arbitrary database failures safe to catch inside the failed scope.
113
+
114
+ S2a alone did not complete Storage. Refactor 35 subsequently implemented the
115
+ neutral SPI, failed-view rules and non-local exits, then passed live PostgreSQL
116
+ acceptance against the applied core/examples pair. Reference SQL code parity
117
+ alone was not used as PostgreSQL execution evidence.
118
+
119
+ ## Refactor 35 verification history
120
+
121
+ Core baseline: ac07b6d4b47167ae404c8ecad8450e80a0087754.
122
+ Examples baseline: ae538996fd276faa3dac0990839e9cf115e6dff6.
123
+ S2b changes the raw SPI and both SQL implementations together. Domain APIs and
124
+ stored formats remain. Candidate checks include InMemory, real SQLite, generic
125
+ resource declarations, scope failures and old/new/old SQLite data compatibility.
126
+ The applied pair above passed all three examples workflows, including
127
+ [PostgreSQL](https://github.com/Raizo-TCS/phronomy-examples/actions/runs/35827495677),
128
+ [SQLite](https://github.com/Raizo-TCS/phronomy-examples/actions/runs/35827495667) and
129
+ [current API](https://github.com/Raizo-TCS/phronomy-examples/actions/runs/35827495646).
130
+ Each job's checkout SHA was verified, not just its green status. Core remote
131
+ workflows had no runs; local core suites supplied that evidence.
132
+
133
+ ## Closure boundary
134
+
135
+ W1, W2a, W2b, S1, S2a, S2b and S2c are applied and verified. S3's bounded Storage
136
+ cleanup and audit are applied and verified in Refactor 36.
137
+ The original review is not fully implemented: the W/S-only inventory omitted
138
+ D02, R03's metadata boundary, R06, R07, R08/D08, parts of R09, R10 and R11.
139
+ See the reconciled inventory below; do not count those proposals as completed.
140
+ Keep the published dependency SVG tied to applied41-01 until Refactor 42 application verification. Performance benchmarking, live-LLM behavior,
141
+ distributed ownership and unknown-outcome recovery policy are separate scopes,
142
+ not silently added requirements for this responsibility refactoring.
143
+
144
+ ## Initial review proposals and current disposition
145
+
146
+ | Initial item | Current assessment and follow-up |
147
+ |---|---|
148
+ | D02 | Applied and verified in Refactor 37: callers construct OperationBinding directly and retain ordering and cancellation contracts. |
149
+ | R03 | Applied and verified in Refactor 38: ExecutionMetadata owns shared durable keys and snapshots; ToolInvocation owns stable identity. Earlier restoration behavior is preserved. |
150
+ | R06 | Applied and verified in Refactor 39: InvocationTransitions owns Tool events, ordered external transitions and state declarations for both builders and Invocation. |
151
+ | R07 | Applied and verified in Refactor 40: ContextAssembler describes preparation through private instruction, record-candidate, candidate-merge and current-input operations. |
152
+ | R08 / D08 | Applied and verified in Refactor 41, one overlapping item: GeneratorVerifier keeps its facade and Result; private WorkflowBuilder, AgentResultReceiver and the moved PipelineState separate graph construction, reception and state. |
153
+ | R09 | Applied and verified in Refactors 42 and 43: Tool binding, declaration rules, Chat construction and explicit state ownership. Existing DSL behavior is retained. |
154
+ | R10 | Implemented in Refactor 44: private actions describe prepared-input installation and runtime Chat construction; Team-generated text describes business tasks. Application verification is pending. |
155
+ | R11 | Applied and verified in Refactor 38: Values::Serializable owns recursive conversion. Caller-specific diagnostics and distinct immutable/canonical/codec contracts remain. |
156
+
157
+ R08/D08 is one work item. R03's Tool restoration and shared metadata ownership
158
+ are complete; do not reopen those contracts. R09's configuration inheritance can
159
+ change public behavior and needs its own explicit decision. These are existing
160
+ proposals rediscovered by the S3 audit, not new performance or distributed-runtime
161
+ requirements. D02, R03/R11, R06, R07 and R08/D08 are applied and verified.
162
+ Refactor 43 application is verified and R09 is closed. Refactor 44 implements
163
+ R10; verify its application before closure. Track the new Tool schema finding
164
+ separately from the original R/D inventory.
165
+
166
+
167
+ ## D02: direct operation binding (Refactor 37, applied)
168
+
169
+ OperationBinding already owns invocation context validation, its private linked
170
+ cancellation token, deadline subscriptions and result-scoped cleanup. Its three
171
+ clients now construct it directly. Execution's pass-through factory has no
172
+ additional behavior and is removed without an alias or replacement factory.
173
+
174
+ Construction remains at the same points: Agent before command admission,
175
+ Blocking only with an explicit context and before Offload submission, and
176
+ Orchestrator for each child before invoke_async. Keep bind/track/close ordering,
177
+ error handling, context selection and cancellation ownership unchanged.
178
+ Orchestrator still uses Execution for fan-out/fan-in; that dependency is intended.
179
+ The internal OperationBinding signature and body, except its ownership comment,
180
+ are unchanged. No class, production file, public API or examples change is added.
181
+
182
+ The distribution is applied and verified at e7e66184. D02 is closed.
183
+ Seven initial-proposal groups remained at that point; R03/R11 are now applied below.
184
+
185
+
186
+ ## R03/R11: shared execution metadata and conversion (Refactor 38, applied)
187
+
188
+ See [the ownership and compatibility design](execution-metadata-and-values.md).
189
+ ExecutionMetadata owns the shared keys, version, snapshot and merge.
190
+ ToolInvocation.semantic_id owns the stable Tool identity, while
191
+ Values::Serializable owns recursive Ruby-to-JSON-tree conversion.
192
+ RecoverySupport retains recovery interpretation; the existing conversion entry
193
+ points retain their distinct diagnostics. No new restoration, transaction or
194
+ external-operation behavior is introduced.
195
+
196
+ Refactor 38 is applied and independently verified at core 690b2823, tree
197
+ 67ea6df833254341043c3fb1e99729d66f9598f6. All 30 full files and the tree match.
198
+ Core 2,970 (61 pending), integration 367 (28 pending), common examples 42 and
199
+ SQLite 116 passed with zero failures, as did API/RBS, style and gem checks.
200
+ R03/R11 are closed. Five groups remained at that point; R06 is now applied below.
201
+ The diagram was synchronized to applied38-01 then and is now applied42-01.
202
+
203
+
204
+ ## R06: Agent transition ownership (Refactor 39, applied)
205
+
206
+ See [the transition ownership design](agent-transition-ownership.md).
207
+ InvocationTransitions owns the six Tool event names, thirteen external event
208
+ families and their ordered transitions, initial phase and state classifications.
209
+ PhaseMachineBuilder compiles the external transitions into state_machines;
210
+ AgentInvocationSessionBuilder passes the same definition to FSMSession.
211
+ AgentInvocation uses the Tool vocabulary to identify payloads it handles.
212
+
213
+ FSMSession still uses only source-state declarations to decide whether an
214
+ external event is accepted or a phase must wait. The machine evaluates guards
215
+ against the current context, after payload application. Engine does not acquire
216
+ Agent policy, and automatic transitions and entry actions keep their owners.
217
+ No new generic DSL, compatibility alias, public API or persistence format is added.
218
+ R10's entry-action names and R09's DSL inheritance semantics are separate work.
219
+
220
+ The implementation preserves callback-failure, Handoff-failure, Handoff-request,
221
+ Tool-request and output-fallback priority, nil-context fallback, guard exceptions,
222
+ approval suspension and resume. Independent behavioral expectations pass on both
223
+ baseline and candidate; full-suite results are in the distribution evidence.
224
+ Refactor 39 is applied and independently verified at core 4d57614a, tree
225
+ 654241da4b2b7f32d988602d28127bc1fa155641. All 10 full files and the tree match.
226
+ Core 2,993 (61 pending), integration 367 (28 pending), common examples 42 and
227
+ SQLite 116 passed with zero failures, as did API/RBS, style and gem checks.
228
+ R06 is closed. Four groups remained then; R07 is now applied below.
229
+ The diagram was synchronized to applied39-01 then and is now applied42-01.
230
+
231
+
232
+ ## R07: Context preparation steps (Refactor 40, applied)
233
+
234
+ See [the preparation design and compatibility boundaries](context-preparation-steps.md).
235
+ ContextAssembler retains its public preparation/finalization boundary and its
236
+ existing collaborators. Seven private operations separate initial/base/Handoff
237
+ instructions, retained instructions, record candidates, Hook/Handoff merging
238
+ and the current-input item. No production class or file is added.
239
+
240
+ The public prepare methods now describe the preparation steps; item IDs,
241
+ provenance and metadata live in the corresponding item-building operation.
242
+ Initial and follow-up paths share generation filtering and candidate merging,
243
+ while preserving their distinct instruction sources, exclusion rules, call
244
+ sequence and ask/complete delivery. Evaluation and content-store effects retain
245
+ their order. Application Policy remains outside the caller's commit transaction;
246
+ finalize remains validation and persistence, without a Policy call.
247
+
248
+ Ten additional contract examples pass against both Refactor 39 and the candidate.
249
+ Four paired initial/follow-up scenarios compare complete Policy input, Prepared,
250
+ Manifest references/bytes and content operations across separate processes.
251
+ Full core/integration/examples/API/type/package gates are in the distribution.
252
+
253
+ Refactor 40 is applied and independently verified at core b3dfbc5a, tree
254
+ dcd9d1bf8efb1b488f9c2b3b1c4e99bdeda6096c. All six files and the tree match.
255
+ Core 3,003 (61 pending), integration 367 (28 pending), common examples 42 and
256
+ SQLite 116 passed with zero failures, as did API/RBS, style, gem and four paired
257
+ preparation scenarios. R07 is closed. Three groups remained at that point; R08/D08 is now applied below.
258
+ The published diagram is applied42-01; keep it until Refactor 43 application checks.
259
+
260
+
261
+ ## R08/D08: GeneratorVerifier ownership (Refactor 41, applied)
262
+
263
+ See [the ownership and event-contract design](generator-verifier-ownership.md).
264
+ The public facade retains configuration, lazy Workflow caching, default parsers
265
+ and Result construction. Private WorkflowBuilder owns graph assembly, request
266
+ startup and convergence. Private AgentResultReceiver converts Agent terminal
267
+ events into correlated Workflow events. PipelineState moves without changing its
268
+ canonical name, fields, correlation checks or mutation behavior.
269
+
270
+ The three implementation files live below generation/generator_verifier. No
271
+ loader change or alias is needed. This updates the original D08 location sketch:
272
+ the pattern already has generation ownership, so it does not move to MultiAgent.
273
+ Draft/review payload meanings remain separate. Only their identical terminal
274
+ classification, completion-notification rescue and failure notification are shared.
275
+ The receiver holds no request-specific mutable state and never mutates Workflow
276
+ context; PipelineState still applies accepted results on the EventLoop.
277
+
278
+ Thirty-nine additional event-contract examples pass on both baseline and candidate,
279
+ including inline completion, failures, parser/notification exceptions, old and
280
+ duplicate results, normalization, convergence, caching and config forwarding.
281
+ The public signature/Result/state contract also matches. Full gates are recorded
282
+ in the distribution. Existing semantics remain: final trust is score-based, even
283
+ if an unapproved high-score draft is finalized at the iteration limit.
284
+
285
+ Refactor 41 is applied and independently verified at core e87eb77f, tree
286
+ 14dc8a546a4fd96e19e0713f7480ca2efa3c331a. All nine files and the full tree match.
287
+ Core 3,042 (61 pending), integration 367 (28 pending), common examples 42 and
288
+ SQLite 116 passed with zero failures, as did API/RBS, style, gem and explicit
289
+ public/Result/state comparisons. R08/D08 is closed; R09 and R10 remain.
290
+ The diagram is applied41-01.
291
+
292
+
293
+ ## R09: Tool binding and declaration rules (Refactor 42, applied)
294
+
295
+ See [the boundary design and inheritance matrix](agent-configuration-and-tool-binding.md).
296
+ Base retains its preparation hook, non-Class passthrough and setting selection.
297
+ Agent::ToolBinding creates alias/filter decorators and forwards custom async
298
+ logical/physical completion. The default async path stays inherited to avoid
299
+ applying filters twice. ToolInvocation and Orchestrator retain their owners.
300
+ No Agent reference or private callback into Base is passed to ToolBinding.
301
+
302
+ Thirty-five new examples pass on both baseline and candidate. Current DSL rules
303
+ are explicit, including non-inherited model/budgets/filters, live parent lookups,
304
+ shared instructions/policy/Tool-list values and inherited aliases that nil does
305
+ not remove. This package does not unify public configuration behavior.
306
+
307
+ Refactor 42 is applied and verified at core 4a57a3c2, tree
308
+ 1a43ec3fecd5457e4314afa3807eb862bbd16b52. All nine files and the tree match.
309
+ Core 3,077 (61 pending), integration 367 (28 pending), examples 42, SQLite 116
310
+ and the packaged persistence contract 41 pass with zero failures. Public
311
+ contracts, API/SPI, types, style and gem loading also pass. This closes the
312
+ first slice; the original R09 Chat/state scope is addressed below.
313
+
314
+ ## R09: Chat construction and explicit state ownership (Refactor 43, applied)
315
+
316
+ See [the Chat/state ownership design](agent-chat-and-state-ownership.md).
317
+ RuntimeChatBuilder owns provider Chat creation, settings and cached instructions.
318
+ StateWriter owns initial root/context/knowledge writes and explicit idle-Agent
319
+ mutations, using the captured root and one transaction. Both live in the existing
320
+ context_assembly directory. They hold no Agent reference or private callbacks.
321
+
322
+ Base keeps the facade, live-owner checks, root proposals and publication. Its
323
+ projection hook preserves instruction/Tool/message order and existing overrides.
324
+ The writer returns root and records only after the transaction returns; Base
325
+ publishes Journal records before replacing the live root. Initial input order,
326
+ idle checks, CAS, revisions, exception identity and rollback behavior are retained.
327
+ Unknown commits, local publication failure and application-owned outer
328
+ transactions retain their existing limitations; no new reconciliation is added.
329
+
330
+ Thirty-seven new behavioral examples pass against both Refactor 42 and the
331
+ candidate. Full core/integration/examples/SQLite and API/SPI/type/style/package
332
+ gates are recorded in the distribution. Static dependency analysis preserves
333
+ all existing cycle memberships, with one new context_assembly -> lifecycle pair.
334
+ This improves responsibility boundaries; it does not remove existing cycles.
335
+
336
+ Refactor 43 is applied and verified at 5c4c0392, tree
337
+ 841bc7b5b28c2d31380ee4a12ffdc22a85ee3c37. All ten files and the full tree match.
338
+ Core 3,114 (61 pending), integration 367 (28 pending), examples 42, SQLite 116
339
+ and gem contract 41 pass with zero failures. R09 is closed; SVG is applied43-01.
340
+ No live-LLM, live PostgreSQL, remote-CI success or performance claim follows
341
+ from that local validation.
342
+
343
+
344
+ ## R10: Entry actions and Team wording (Refactor 44 candidate)
345
+
346
+ See [the naming and compatibility boundary](entry-action-and-team-wording.md).
347
+ Only two private action names and two generated Team strings change in production.
348
+ State/event vocabulary and action bodies stay unchanged. Legacy saved operation
349
+ results are returned as stored; new operations use business-task wording.
350
+ The original R/D inventory has no other unimplemented item, but R10 remains
351
+ pending application verification.
352
+
353
+ ## New open finding: Tool parameter schema recording
354
+
355
+ The [Tool schema recording gap](tool-schema-recording-gap.md) was reproduced on
356
+ Refactor 43 and Refactor 44 with RubyLLM 1.16.0. The actual schema reader is
357
+ `params_schema`, whereas ToolDefinitionSet records `{}` when its expected
358
+ `parameters_schema` reader is absent. A required/type change can evade the saved
359
+ comparison. This is the next correctness issue to design, with explicit handling
360
+ of historical manifests. It is not fixed by R10 or by passing its recovery tests.
361
+
362
+ ## Refactor 44 applied; Refactor 45 migration candidate
363
+
364
+ R10 was applied at 99ee43cd7b48174d825d20876fc38bbe47e6da11, tree
365
+ 34de332df150ff28ac93b2d04e099197f4a214d1, and verified. The original R/D inventory
366
+ is closed. Earlier candidate wording above is historical.
367
+
368
+ RubyLLM 2.0.0 now supplies the awaited provider-neutral output cap.
369
+ [Refactor 45](rubyllm-2-token-ownership.md) implements the dependency/API migration,
370
+ input-only registry budgeting, output-cap forwarding, schema recording/comparison
371
+ and coordinated examples migration. The schema issue is addressed in this candidate;
372
+ old empty-schema manifests require completion on the original version before upgrade.
373
+ Local verification and the exact package trees are recorded in the distribution.
374
+ User application verification remains outstanding; this is not a published release.
@@ -0,0 +1,82 @@
1
+ # RubyLLM 2.0 and token ownership (Refactor 45)
2
+
3
+ This candidate targets RubyLLM 2.0.x (`~> 2.0.0`), verified with 2.0.0.
4
+ It implements the previously deferred token-ownership plan against the current
5
+ 0.26.0 refactoring branch. It does not publish or renumber the Phronomy gem.
6
+
7
+ ## Ownership
8
+
9
+ | Concern | Owner and behavior |
10
+ |---|---|
11
+ | Input capability | RubyLLM model registry `context_window`, defined by RubyLLM 2 as maximum input tokens |
12
+ | Model lookup | `RubyLLM.models.find(model, provider: provider)` |
13
+ | Input budget | Phronomy `TokenBudget(max_input_tokens:)`, using that limit directly |
14
+ | Unknown/invalid input limit | No hard token budget; no invented limit or reserve |
15
+ | Requested output cap | Agent `max_output_tokens`, positive Integer; stored in model_config |
16
+ | Output request rendering | RubyLLM `Chat#with_max_output_tokens`; all wire names remain upstream |
17
+ | Context selection | Phronomy ContextPolicy and final Manifest validation |
18
+ | Replay | Recorded Manifest segments and request intent; no current-budget reselection |
19
+
20
+ Remove application calls to `Agent.context_window` and
21
+ `configuration.default_output_reserve`. They no longer exist.
22
+ `before_llm_input` patches containing `context_window` raise ConfigurationError;
23
+ register custom/local model metadata through RubyLLM's public registry loader.
24
+ `max_output_tokens` does not reduce the input budget and is not inferred from
25
+ registry output capacity. Omit it to use RubyLLM/provider defaults.
26
+ The obsolete InvalidContextBudgetConfigurationError has also been removed.
27
+ New manifests have assembly policy version 9. Historical model_config keys are
28
+ not rewritten during materialization, and the runtime builder forwards only
29
+ supported request settings.
30
+
31
+ ## RubyLLM 2 compatibility
32
+
33
+ The adapter uses `with_tools`, keyword Tool execution, `parameters_schema`,
34
+ `provider_options`, `Message#model`, and `Tokens#cache_read/#cache_write`.
35
+ Phronomy's `param`, `params`, `with_params`, `params_schema`, and `provider_params`
36
+ remain available as its own Tool contract. RubyLLM 2's derived class tool name
37
+ is used when no explicit name is supplied. Structured historical content is
38
+ encoded as JSON text when materialized into RubyLLM 2 Messages. Stored canonical
39
+ content is unchanged. Phronomy TokenUsage retains its cached/cache_creation names;
40
+ recovery reads both the historical and new RubyLLM counter keys.
41
+
42
+ Cached instructions use `with_instructions(..., cache_until_here:)`.
43
+ No RubyLLM 1.x guard, monkeypatch, or provider-specific output mapping remains.
44
+ Applications choose protocol settings in RubyLLM. Its OpenAI default is Responses;
45
+ local Chat Completions endpoints must configure `openai_protocol = :chat_completions`.
46
+
47
+ Tool batches are intercepted through `after_message`, after RubyLLM has appended
48
+ the complete assistant Message and before RubyLLM's approval/Tool execution loop.
49
+ Phronomy's existing authorization, suspension and batch execution paths therefore
50
+ remain authoritative. Tool classes and their approval declarations are not
51
+ rewritten to bypass RubyLLM's gate.
52
+
53
+ ## Saved Tool definitions and deployment
54
+
55
+ The previous empty-schema fallback concealed argument changes. New definitions
56
+ record the actual schema and provider options and compare them canonically.
57
+ Changes to argument type, requiredness, enum or provider options are rejected.
58
+
59
+ An old `{}` schema cannot establish which parameters were originally authorized.
60
+ The migration fails closed with an explicit diagnostic when such a saved
61
+ Manifest is materialized; it does not synthesize or weaken historical definitions.
62
+ Before updating, finish outstanding Agent, Workflow and Team operations that may
63
+ need old Tool-bearing manifests on the old core/RubyLLM combination, and retain
64
+ backups of durable storage. Do not perform a rolling upgrade with mixed versions
65
+ sharing those in-flight executions. Completed history is not rewritten; starting
66
+ a new invocation creates a current schema-bearing manifest. This is a deployment
67
+ boundary, not an automatic historical-data repair.
68
+
69
+ ## Examples and verification
70
+
71
+ The shared examples configuration registers explicit PHRONOMY_CONTEXT_WINDOW or
72
+ observed local metadata via `RubyLLM.models.load_from_json`, retaining other model
73
+ entries. An unavailable local limit remains nil, including when the local server
74
+ uses a cloud model's name. Code-review chunking requires known metadata explicitly.
75
+ Request output caps are independent constants. Rails examples use the same setup.
76
+
77
+ Tests cover provider-qualified input budgets, missing metadata, output forwarding,
78
+ forbidden hook overrides, saved intent without reselection, actual Tool schema
79
+ comparison, old/new usage counters, Responses Tool/approval/streaming execution,
80
+ and existing Chat Completions and durability behavior. Protocol rendering remains
81
+ RubyLLM's responsibility. Distribution evidence distinguishes HTTP stubs and local
82
+ SQLite from live providers, PostgreSQL and the remote Ruby-version CI matrix.
@@ -0,0 +1,50 @@
1
+ # Historical finding: Tool parameter schema is absent from saved definitions
2
+
3
+ ## Observed mismatch
4
+
5
+ During Refactor 44 verification, Ruby 3.3.6 with RubyLLM 1.16.0 reproduced the
6
+ following on both applied Refactor 43 and the Refactor 44 candidate:
7
+
8
+ 1. The prepared Tool exposes its actual argument schema through `params_schema`.
9
+ 2. `Agent::ToolDefinitionSet.build` asks for `parameters_schema`, which this Tool
10
+ does not respond to, and stores an empty Hash for that field.
11
+ 3. `select_definitions` compares the stored definitions exactly, but a change
12
+ from optional string `summary` to required integer `summary` is accepted
13
+ because neither definition contains its actual argument schema.
14
+
15
+ The LLM request still includes the actual schema. The missing information is in
16
+ Phronomy's recorded definition and therefore in the comparison boundary. Tool
17
+ names and top-level descriptions are still compared; this finding does not mean
18
+ all Tool identity checks are absent. The source of ToolDefinitionSet is unchanged
19
+ by R10, and no claim is made about untested RubyLLM versions.
20
+
21
+ ## Consequence
22
+
23
+ Recovery/context materialization cannot reject that incompatible argument change
24
+ through the saved definition comparison. The R10 parameter-description change
25
+ also does not cause a mismatch on this tested version. Passing old/new recovery
26
+ checks must not be presented as evidence that parameter compatibility is guarded.
27
+
28
+ ## Required follow-up
29
+
30
+ This is an open correctness issue, separate from the R10 naming cleanup.
31
+ A follow-up should obtain the schema actually used by the supported adapter,
32
+ record it in canonical form and compare it during context selection/recovery.
33
+ It must also specify how to treat old saved definitions whose schema is `{}`.
34
+ Blindly switching the reader would make new definitions conflict with historical
35
+ manifests; blindly ignoring mismatches would erase the intended guard.
36
+
37
+ Acceptance requires meaningful parameter-change rejection, matching-schema
38
+ continuation, explicit treatment of missing historical schema, adapter-version
39
+ coverage and old/new recovery validation. Until that work is accepted, retain
40
+ this issue in the current work list. Refactor 44 does not silently migrate records
41
+ or change the general Tool comparison contract.
42
+
43
+ ## Refactor 45 resolution candidate
44
+
45
+ [The RubyLLM 2 migration](rubyllm-2-token-ownership.md) removes the empty fallback,
46
+ records the actual schema/provider options and rejects incompatible definitions.
47
+ It explicitly rejects historical empty schemas when materializing in-flight
48
+ manifests. Matching current definitions continue normally. The original observation
49
+ above is retained as evidence; it is not a description of the new implementation.
50
+ Application verification of Refactor 45 remains pending.
@@ -100,7 +100,7 @@ span.
100
100
 
101
101
  ### `multi_agent.turn`
102
102
 
103
- One coarse `MultiAgent::Runner` user turn. Handoff does not create a mandatory
103
+ One coarse `MultiAgent::HandoffRunner` user turn. Handoff does not create a mandatory
104
104
  long-lived span type.
105
105
 
106
106
  ## 6. Correlation and identity
@@ -0,0 +1,104 @@
1
+ # Workflow terminal ownership: design and validation
2
+
3
+ Implementation baseline: core `01cd2f57549f6d1e60825254f4520d0f123e651c`
4
+ (Refactor 32 applied) and examples `2f8b467f1268dd21de4c02b1c90c8bdd211d1feb`,
5
+ 2026-09-23. W2a and W2b are applied and verified; W2b is core
6
+ `fcd434c45ad98e5c93953cbce1ffef3c12246894` (Refactor 33). The adopted private contract is
7
+ [ADR-056](../decisions/056-workflow-terminal-policy-ownership.md).
8
+
9
+ ## Role and consumers
10
+
11
+ FSMSession drives one live state machine on EventLoop. WorkflowRunner assembles
12
+ Workflow transitions, stream observation and any durable terminal save.
13
+ AgentInvocationSessionBuilder uses the same engine for input, LLM and Tool
14
+ progression; ToolInvocationSessionBuilder uses it for authorization, approval
15
+ and Tool execution. Therefore the session stays in Engine.
16
+
17
+ The former leak was narrower: Engine recognized the Workflow persistence event
18
+ and interpreted its save outcomes. WorkflowTerminalPolicy now owns that rule.
19
+
20
+ ## Ownership and concrete boundary
21
+
22
+ | Owner | Responsibility |
23
+ |---|---|
24
+ | FSMSession | Identity/sink, transitions, live context, pending terminal kind/notification flag, event acceptance and final notification/event ordering. |
25
+ | WorkflowTerminalPolicy | Start the injected save callback; recognize the Workflow result event; map its outcome to a generic terminal decision. |
26
+ | FSMProtocol::TerminalDecision | Immutable `action` and `error` value shared by a domain policy and the session. No live session authority. |
27
+ | WorkflowRunner | Construct a policy for durable execution; retain snapshot capture, one save, F1 readback and caller completion. |
28
+ | WorkflowExecutionRegistry | Admission, owner tokens, session routing binding and recovery-required ownership. |
29
+ | EventLoop | Event routing, management events, retirement, source completion and shutdown. |
30
+
31
+ Runner builds a policy only when both repository and persist are enabled.
32
+ Agent, Tool and ephemeral Workflow need no dummy policy or delayed completion.
33
+ The policy retains only its persistence callback, with no lifecycle flags.
34
+
35
+ The three private operations are `start(terminal_type:, context:, event_sink:)`,
36
+ `handles?(event)` and `decision_for(event)`. Start does not return completion
37
+ permission. The decision value maps Workflow success to `complete`, known
38
+ failure to `fail`, and unresolved uncertainty to `retire`. Failure preserves the
39
+ original exception or the existing missing-error fallback. Invalid outcomes
40
+ remain errors. Engine no longer branches on Workflow's event or outcome values.
41
+
42
+ FSMSession alone tracks `running`, `awaiting_terminal`, and its final lifecycle
43
+ state. Matching early events are discarded before invoking decision_for;
44
+ ordinary events cannot advance while awaiting; events after done are ignored.
45
+ The retirement action reuses the existing recovery-required management route.
46
+
47
+ ## Preserved durable ordering
48
+
49
+ 1. Session reaches a logical wait/completion boundary and captures metadata.
50
+ 2. Session marks itself awaiting a decision before invoking the policy.
51
+ 3. Runner marks admission persisting_terminal and captures an immutable command.
52
+ 4. Offload saves once and reconciles an uncertain result when possible.
53
+ 5. The bound EventSink returns the result to that session on EventLoop.
54
+ 6. The policy interprets the result only while the session accepts it.
55
+ 7. A complete decision permits the deferred observer, then the terminal event.
56
+ 8. EventLoop retires the session; Runner releases admission before settling the caller.
57
+
58
+ An observer exception still uses Refactor 32's ordinary error path, with the
59
+ already confirmed snapshot retained. No observer retry or extra save is added.
60
+
61
+ Unresolved uncertainty instead retires the session and retains recovery-required
62
+ admission without falsely settling the caller. Normal shutdown clears that
63
+ ownership and ends the dispatcher, while the caller remains pending; unexpected
64
+ dispatcher failure retains its separate existing waiter-cleanup behavior. This
65
+ change does not promise that normal shutdown resolves an unknown commit.
66
+
67
+ ## Alternatives and compatibility
68
+
69
+ Moving the full session would introduce Workflow dependencies into Agent/Tool.
70
+ Renaming event strings in Engine would leave semantic ownership unchanged.
71
+ Subclass/prepend overrides would recreate the hidden execution path removed by
72
+ W1. Saving after retirement or settling on a worker would break the barrier.
73
+ The injected policy keeps each rule at its existing execution authority.
74
+
75
+ The internal constructor changes from terminal_barrier to terminal_policy;
76
+ there is no compatibility alias or new public plugin API. Without a policy,
77
+ Engine does not reserve a Workflow-specific event name. Production Workflow
78
+ emits the result event only when it has injected its durable policy.
79
+ Public signatures, Workflow command/result identities, data records and Storage
80
+ SPI stay unchanged. One policy class and one decision value type are added;
81
+ this is responsibility separation, not a total-line-count reduction.
82
+
83
+ ## Acceptance evidence
84
+
85
+ | Scenario | Test boundary |
86
+ |---|---|
87
+ | Immediate completion/halt and Agent/Tool | Existing Workflow/Agent/Tool suites and generic no-policy completion. |
88
+ | Delayed save and halted stream | Real Runtime admission tests prove no early result/notification. |
89
+ | Portable failures and F1 post/pre/conflict/unreadable | Existing save tests plus real Runtime pre-state and uncertainty tests. |
90
+ | Unknown result and normal shutdown | Admission retained until shutdown, session unbound, caller remains pending. |
91
+ | Early/ordinary/duplicate decisions | Non-Workflow policy/session contract and Workflow policy wiring tests. |
92
+ | Late sink and new incarnation | Real Runtime rejects an old sink for the same logical Workflow ID. |
93
+ | Terminal observer failure | Refactor 32's four public stream regressions. |
94
+ | Submission rejection and delivery rejection | Existing error path releases admission; rejected delivery logs without retry. |
95
+ | Invalid outcomes and missing error | Workflow policy through the real Runner/session assembly. |
96
+ | Load, types, API, gem and source boundary | Full validation and private ownership regression assertions. |
97
+
98
+ The pre-state, uncertainty/shutdown, stale-sink and rejected-delivery scenarios
99
+ also pass on the Refactor 32 baseline; they characterize preserved behavior.
100
+ New protocol tests establish the extracted ownership contract. Refactor 33
101
+ application verification completed W2b. Storage S1/S2 followed and passed on
102
+ Refactor 35; see the [closure review](refactoring-closure.md) for S3 and the
103
+ current applied/candidate boundary. The earlier Refactor 32 baseline remains
104
+ historical evidence for preserved behavior.