phronomy 0.22.0 → 0.24.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +3 -4
  3. data/CHANGELOG.md +215 -10
  4. data/CONTRIBUTING.md +81 -9
  5. data/README.md +15 -6
  6. data/VERIFY.sh +587 -0
  7. data/benchmark/bench_agent_invoke.rb +2 -2
  8. data/benchmark/bench_context_assembler.rb +39 -68
  9. data/benchmark/bench_regression.rb +2 -2
  10. data/docs/architecture/agent-context.md +174 -0
  11. data/docs/architecture/before-llm-input.md +78 -0
  12. data/docs/architecture/context-management.md +232 -0
  13. data/docs/architecture/knowledge-and-rag.md +130 -0
  14. data/docs/architecture/multi-agent-handoff.md +147 -0
  15. data/docs/architecture/persistence.md +186 -0
  16. data/docs/architecture/removed/agent-context.md +72 -0
  17. data/docs/architecture/security-boundaries.md +173 -0
  18. data/docs/architecture/tracing.md +194 -0
  19. data/docs/architecture.md +89 -0
  20. data/docs/archive/design/archived/04_api_design.md +507 -0
  21. data/docs/archive/design/archived/09_guardrails.md +186 -0
  22. data/docs/archive/design/archived/17_rails_integration.md +175 -0
  23. data/docs/archive/design/historical/00_design_philosophy.md +122 -0
  24. data/docs/archive/design/historical/01_rubyllm_evaluation.md +178 -0
  25. data/docs/archive/design/historical/06_design_decisions.md +143 -0
  26. data/docs/changelog/0.14-and-earlier.md +1 -1
  27. data/docs/decisions/001-rubyllm-as-provider-layer.md +6 -1
  28. data/docs/decisions/002-workflow-context-immutability.md +26 -1
  29. data/docs/decisions/006-no-built-in-guardrails.md +2 -1
  30. data/docs/decisions/012-canonical-execution-log-and-context-policy.md +120 -38
  31. data/docs/decisions/014-unified-persistence-durable-state.md +9 -2
  32. data/docs/decisions/016-semantic-multi-agent-handoff.md +114 -0
  33. data/docs/decisions/017-design-authority-and-adr-governance.md +200 -0
  34. data/docs/decisions/018-durability-guarantees-and-failure-model.md +488 -0
  35. data/docs/decisions/019-filter-contract-and-security-boundaries.md +229 -0
  36. data/docs/decisions/020-canonical-workflow-instance-identity.md +177 -0
  37. data/docs/decisions/021-generic-agent-invocation-identity-removal.md +119 -0
  38. data/docs/decisions/022-agent-execution-parent-identity-and-runtime-routing-boundary.md +193 -0
  39. data/docs/decisions/023-fsm-session-incarnation-identity-and-routing.md +139 -0
  40. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +188 -0
  41. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +249 -0
  42. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +257 -0
  43. data/docs/decisions/027-llm-adapter-provider-boundary.md +93 -0
  44. data/docs/decisions/028-preparing-recovery-replay-contract.md +106 -0
  45. data/docs/decisions/029-semantic-completion-and-application-effect-boundary.md +220 -0
  46. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +235 -0
  47. data/docs/decisions/031-durable-multi-agent-coordination.md +301 -0
  48. data/docs/decisions/README.md +176 -0
  49. data/docs/design/durable-semantic-coordination/CHANGELOG_V2_REVISION_2.md +33 -0
  50. data/docs/design/durable-semantic-coordination/CONTINUATION_DECISION_REFACTOR.md +191 -0
  51. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +862 -0
  52. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +106 -0
  53. data/docs/design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md +179 -0
  54. data/docs/design/durable-semantic-coordination/RESPONSIBILITY_BOUNDARY_REVIEW.md +302 -0
  55. data/docs/features.md +65 -11
  56. data/docs/getting-started.md +77 -45
  57. data/docs/migrations/0.19.md +14 -7
  58. data/docs/migrations/0.22.md +390 -0
  59. data/docs/migrations/durable-semantic-coordination-v2.md +65 -0
  60. data/docs/persistence-backends.md +129 -40
  61. data/docs/runtime-and-concurrency.md +227 -33
  62. data/examples/README.md +13 -0
  63. data/lib/phronomy/agent/agent_execution.rb +21 -17
  64. data/lib/phronomy/agent/agent_invocation.rb +288 -93
  65. data/lib/phronomy/agent/agent_invocation_session_builder.rb +236 -202
  66. data/lib/phronomy/agent/agent_root.rb +3 -3
  67. data/lib/phronomy/agent/approval_evaluation_request.rb +37 -19
  68. data/lib/phronomy/agent/async_event_api.rb +162 -72
  69. data/lib/phronomy/agent/base.rb +416 -181
  70. data/lib/phronomy/agent/concerns/before_llm_input.rb +1 -1
  71. data/lib/phronomy/agent/context_assembler.rb +437 -178
  72. data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
  73. data/lib/phronomy/agent/context_plan.rb +18 -13
  74. data/lib/phronomy/agent/context_plan_validator.rb +246 -88
  75. data/lib/phronomy/agent/context_policies/default.rb +123 -34
  76. data/lib/phronomy/agent/context_policy.rb +109 -3
  77. data/lib/phronomy/agent/context_policy_input.rb +244 -0
  78. data/lib/phronomy/agent/context_policy_input_builder.rb +241 -0
  79. data/lib/phronomy/agent/exact_execution.rb +153 -0
  80. data/lib/phronomy/agent/execution_cancellation.rb +25 -0
  81. data/lib/phronomy/agent/execution_coordinator.rb +2417 -572
  82. data/lib/phronomy/agent/handoff.rb +43 -0
  83. data/lib/phronomy/agent/handoff_capability_factory.rb +45 -0
  84. data/lib/phronomy/agent/handoff_context.rb +120 -0
  85. data/lib/phronomy/agent/handoff_execution_coordinator.rb +143 -0
  86. data/lib/phronomy/agent/handoff_policy.rb +143 -0
  87. data/lib/phronomy/agent/handoff_projection.rb +207 -0
  88. data/lib/phronomy/agent/handoff_request.rb +45 -0
  89. data/lib/phronomy/agent/handoff_runner.rb +178 -0
  90. data/lib/phronomy/agent/handoff_state.rb +43 -0
  91. data/lib/phronomy/agent/journal_record.rb +17 -4
  92. data/lib/phronomy/agent/llm_input_build_context.rb +1 -1
  93. data/lib/phronomy/agent/llm_input_manifest.rb +277 -2
  94. data/lib/phronomy/agent/llm_operation_result.rb +12 -7
  95. data/lib/phronomy/agent/phase_machine_builder.rb +19 -7
  96. data/lib/phronomy/agent/provider_call_outcome.rb +23 -7
  97. data/lib/phronomy/agent/recovery_coordinator/continuation.rb +174 -0
  98. data/lib/phronomy/agent/recovery_coordinator/installation.rb +381 -0
  99. data/lib/phronomy/agent/recovery_coordinator/resolution.rb +511 -0
  100. data/lib/phronomy/agent/recovery_coordinator.rb +217 -0
  101. data/lib/phronomy/agent/recovery_support.rb +504 -0
  102. data/lib/phronomy/agent/ruby_llm_materializer.rb +16 -13
  103. data/lib/phronomy/agent/selection/candidate.rb +53 -0
  104. data/lib/phronomy/agent/selection/constraint.rb +49 -0
  105. data/lib/phronomy/agent/shared_state.rb +38 -1
  106. data/lib/phronomy/agent/tool_approval_request.rb +33 -5
  107. data/lib/phronomy/agent/tool_definition_set.rb +49 -3
  108. data/lib/phronomy/agent/tool_invocation.rb +339 -103
  109. data/lib/phronomy/agent/tool_invocation_session_builder.rb +49 -45
  110. data/lib/phronomy/agent.rb +20 -2
  111. data/lib/phronomy/agent_already_exists_error.rb +5 -0
  112. data/lib/phronomy/agent_purged_error.rb +5 -0
  113. data/lib/phronomy/engine/concurrency/offload_pool.rb +17 -3
  114. data/lib/phronomy/engine/concurrency/physical_completion_task.rb +135 -0
  115. data/lib/phronomy/engine/event_loop.rb +622 -63
  116. data/lib/phronomy/engine/fsm_session.rb +194 -21
  117. data/lib/phronomy/engine/runtime/agent_ownership_registry.rb +352 -0
  118. data/lib/phronomy/engine/runtime/team_ownership_registry.rb +77 -0
  119. data/lib/phronomy/engine/runtime.rb +92 -20
  120. data/lib/phronomy/generator_verifier.rb +12 -14
  121. data/lib/phronomy/invocation_context.rb +9 -29
  122. data/lib/phronomy/multi_agent/admission_registry.rb +51 -0
  123. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +134 -0
  124. data/lib/phronomy/multi_agent/fan_out_invocation.rb +24 -33
  125. data/lib/phronomy/multi_agent/fan_out_session_builder.rb +12 -19
  126. data/lib/phronomy/multi_agent/orchestrator.rb +71 -26
  127. data/lib/phronomy/multi_agent/team_coordinator.rb +473 -125
  128. data/lib/phronomy/multi_agent/team_execution.rb +44 -0
  129. data/lib/phronomy/multi_agent/team_root.rb +41 -0
  130. data/lib/phronomy/persistence/durable_codec.rb +706 -0
  131. data/lib/phronomy/persistence/durable_record.rb +117 -0
  132. data/lib/phronomy/persistence/in_memory.rb +471 -133
  133. data/lib/phronomy/persistence/migration/initial_format_migration.rb +226 -0
  134. data/lib/phronomy/persistence/repository_facades.rb +535 -0
  135. data/lib/phronomy/persistence.rb +174 -40
  136. data/lib/phronomy/recovery.rb +186 -0
  137. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
  138. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +2 -1
  139. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +19 -19
  140. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +3 -3
  141. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
  142. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +137 -0
  143. data/lib/phronomy/testing/persistence_contract.rb +5 -0
  144. data/lib/phronomy/tools/agent.rb +1 -1
  145. data/lib/phronomy/tracing/automatic.rb +176 -0
  146. data/lib/phronomy/tracing/base.rb +11 -2
  147. data/lib/phronomy/tracing/langfuse_tracer.rb +20 -12
  148. data/lib/phronomy/version.rb +1 -1
  149. data/lib/phronomy/workflow.rb +3 -6
  150. data/lib/phronomy/workflow_context.rb +14 -5
  151. data/lib/phronomy/workflow_recovery.rb +123 -0
  152. data/lib/phronomy/workflow_runner.rb +468 -256
  153. data/lib/phronomy.rb +6 -0
  154. data/scripts/api_snapshot.rb +12 -0
  155. data/sig/phronomy/agent.rbs +209 -7
  156. data/sig/phronomy/handoff.rbs +41 -0
  157. data/sig/phronomy/multi_agent.rbs +35 -0
  158. data/sig/phronomy/persistence.rbs +123 -4
  159. data/sig/phronomy/runtime.rbs +1 -4
  160. data/sig/phronomy/workflow.rbs +2 -2
  161. data/sig/phronomy.rbs +10 -0
  162. metadata +84 -18
  163. data/examples/workflows/agent_event_mapping.rb +0 -101
  164. data/examples/workflows/generic_task_event_mapping.rb +0 -66
  165. data/lib/phronomy/agent/activation_registry.rb +0 -28
  166. data/lib/phronomy/agent/agent_execution_activation.rb +0 -172
  167. data/lib/phronomy/agent/context_candidate.rb +0 -47
  168. data/lib/phronomy/agent/context_parts/budget/token_budget_packer.rb +0 -53
  169. data/lib/phronomy/agent/context_parts/requirements/required_context_resolver.rb +0 -56
  170. data/lib/phronomy/agent/context_parts/selectors/recent_first_selector.rb +0 -30
  171. data/lib/phronomy/agent/context_parts/unit_builders/dependency_aware_unit_builder.rb +0 -118
  172. data/lib/phronomy/agent/context_policy_descriptor.rb +0 -49
  173. data/lib/phronomy/agent/context_policy_registry.rb +0 -46
  174. data/lib/phronomy/agent/context_request.rb +0 -35
  175. data/lib/phronomy/agent/context_selection_unit.rb +0 -38
  176. data/lib/phronomy/agent/derived_content_spec.rb +0 -34
  177. data/lib/phronomy/agent/runner.rb +0 -97
  178. data/lib/phronomy/multi_agent/handoff.rb +0 -64
@@ -0,0 +1,301 @@
1
+ # ADR-031: Durable Multi-Agent Semantic Coordination
2
+
3
+ ## Status
4
+
5
+ Accepted. V2 revision 2, 2026-09-06.
6
+
7
+ User approval covers the V2 boundary and the five recovery-contract clarifications.
8
+ Acceptance is design authority; it is not a claim of repository integration or test success.
9
+
10
+ ## Date
11
+
12
+ 2026-09-06
13
+
14
+ ## Context
15
+
16
+ Phronomy exposes:
17
+
18
+ - `MultiAgent::Orchestrator < Agent::Base`, with child Agents/Tools and fan-out
19
+ helpers; and
20
+ - `MultiAgent::TeamCoordinator`, with coordinator-generated tasks and a worker pool.
21
+
22
+ Individual AgentExecutions are durable, but process-local coordination state is
23
+ not. Losing child identities, task assignments or confirmed worker outcomes can
24
+ cause Phronomy to repeat semantic work it owns.
25
+
26
+ The previous proposal also attempted to make standalone fan-out convenience APIs,
27
+ arbitrary Team aggregation callbacks and terminal Application callbacks durable.
28
+ Responsibility review found those parts too broad.
29
+
30
+ This ADR therefore defines durability at the **framework-owned semantic
31
+ coordination boundary**, not at every callback/convenience API boundary.
32
+
33
+ ## Decision
34
+
35
+ ### 1. MultiAgent durability means semantic progress recovery
36
+
37
+ For a durable MultiAgent operation:
38
+
39
+ ```text
40
+ process/runtime loss
41
+ -> reconstruct from durable coordination facts
42
+ -> reuse confirmed child/worker outcomes
43
+ -> recover exact unfinished executions
44
+ -> admit absent reserved executions only after authoritative read/admission
45
+ -> resolve unknown external effects through existing Agent Recovery
46
+ ```
47
+
48
+ FSMSession, Task, callback and Runtime queues remain disposable.
49
+
50
+ ### 2. Orchestrator durability is rooted in an existing Orchestrator AgentExecution
51
+
52
+ `MultiAgent::Orchestrator < Agent::Base` already has canonical Agent identity.
53
+
54
+ When child coordination occurs **inside an existing Orchestrator AgentExecution**,
55
+ that AgentExecution references an immutable coordination snapshot containing, as
56
+ needed:
57
+
58
+ ```text
59
+ coordination kind / phase
60
+ child slot
61
+ child Agent definition identity/version
62
+ reserved child agent_id
63
+ reserved child execution_id
64
+ restart-required input/config refs
65
+ child semantic state
66
+ result_ref / error_ref
67
+ on_error / max_concurrency semantic options
68
+ ```
69
+
70
+ No separate Orchestrator repository or generic multi-agent execution ID is added.
71
+
72
+ ### 3. Existing fan-out Runtime FSM remains reconstructable machinery
73
+
74
+ `FanOutInvocation` / `FSMSession` remain Runtime projections.
75
+
76
+ Recovery builds a fresh runtime invocation/session from the durable coordination
77
+ snapshot and fresh Runtime identities.
78
+
79
+ ### 4. Framework-owned child identities are reserved before semantic work
80
+
81
+ Before a durable Orchestrator child begins:
82
+
83
+ ```text
84
+ reserve child agent_id
85
+ reserve child execution_id
86
+ persist parent child slot + restart-required refs
87
+ then create/load child and start exact reserved execution
88
+ ```
89
+
90
+ Recovery distinguishes absent/nonterminal/terminal exact child state and never
91
+ creates a replacement simply because Runtime callbacks were lost.
92
+
93
+ ### 5. Durable child definitions must be reconstructable from stable wiring
94
+
95
+ For the durable path, a child Agent class must be resolvable from stable current
96
+ Orchestrator/Application wiring, initially the concrete Orchestrator class's
97
+ registered subagents.
98
+
99
+ Invocation-only anonymous/arbitrary class handles are not persisted.
100
+
101
+ This restriction applies only to APIs/paths that claim restart durability.
102
+
103
+ ### 6. Standalone `dispatch_parallel*` / `fan_out*` remain Runtime-only convenience APIs
104
+
105
+ A direct Application call to:
106
+
107
+ ```ruby
108
+ orchestrator.dispatch_parallel(...)
109
+ orchestrator.fan_out(...)
110
+ ```
111
+
112
+ outside a live parent Orchestrator AgentExecution does **not** create a synthetic
113
+ AgentExecution solely for durability.
114
+
115
+ It keeps current-process semantics and may continue accepting Runtime-only Agent
116
+ class wiring.
117
+
118
+ If durable fan-out is required, the Application must place the work under:
119
+
120
+ - an Orchestrator AgentExecution with stable child wiring; or
121
+ - an Application Workflow when the operation is application-process
122
+ orchestration.
123
+
124
+ This avoids inventing durable parent identity for a convenience call.
125
+
126
+ ### 7. Durable framework-owned Orchestrator children share the parent Persistence domain
127
+
128
+ A durable parent/child coordination path uses the same Persistence domain.
129
+
130
+ External remote effects reached through Tools/Application integration remain X0
131
+ external effects.
132
+
133
+ ### 8. TeamCoordinator is a purpose-specific durable semantic entity
134
+
135
+ TeamCoordinator remains under `MultiAgent`, not `Agent::Base`.
136
+
137
+ It gains:
138
+
139
+ ```text
140
+ team_id
141
+ team_execution_id
142
+ team_definition id/version
143
+ TeamRoot
144
+ TeamExecution
145
+ ```
146
+
147
+ This is retained because Phronomy itself owns the Team queue/assignment/worker
148
+ abstraction.
149
+
150
+ ### 9. Team task queue and worker assignment are durable facts
151
+
152
+ TeamExecution durably records:
153
+
154
+ ```text
155
+ canonical tasks
156
+ task-generation finalized state
157
+ worker slots / stable worker agent_id
158
+ task -> worker assignment
159
+ reserved worker execution_id
160
+ worker terminal result/error
161
+ final Team result/error
162
+ ```
163
+
164
+ Before worker semantic execution starts, its assignment and reserved exact
165
+ execution identity are committed.
166
+
167
+ ### 10. Worker identity is stable within one TeamExecution
168
+
169
+ A worker slot reuses its logical Agent identity for that TeamExecution so worker
170
+ context/transcript semantics remain coherent across assigned tasks.
171
+
172
+ This ADR does not require worker identity/history to survive into another
173
+ TeamExecution.
174
+
175
+ ### 11. Team scheduler is a replay-safe decision function
176
+
177
+ Application `schedule` may run again while no assignment has been durably
178
+ committed.
179
+
180
+ Contract:
181
+
182
+ - it must not perform externally observable one-shot effects;
183
+ - it selects from the supplied available worker projection;
184
+ - repeated execution before assignment commit is allowed;
185
+ - after assignment commit, recovery uses the durable assignment and does not
186
+ rerun scheduling for that task.
187
+
188
+ No scheduler result needs a separate unknown-outcome protocol.
189
+
190
+ ### 12. Team aggregation is pure/replay-safe result computation
191
+
192
+ Application `aggregate` receives canonical durable assignment results.
193
+
194
+ Contract:
195
+
196
+ - no externally observable one-shot side effects;
197
+ - repeated invocation with the same canonical assignments must be semantically
198
+ equivalent;
199
+ - if process loss occurs before aggregate result/error is durably committed,
200
+ Phronomy may invoke `aggregate` again;
201
+ - on normal return/raise, Phronomy durably records the final result/error before
202
+ Team terminalization.
203
+
204
+ There is no `aggregation=started -> outcome unknown -> manual resolve` protocol.
205
+
206
+ Applications perform external post-Team effects after obtaining/reconciling the
207
+ Team result.
208
+
209
+ ### 13. Team progress and terminal callbacks are Runtime-only
210
+
211
+ Streaming task-completion callbacks and final Application notifications are
212
+ current-process observations.
213
+
214
+ Canonical task/worker/Team semantic outcomes are durable; callback delivery is
215
+ not.
216
+
217
+ No Team delivery-pending index or restart redelivery obligation is introduced.
218
+
219
+ ### 14. Workflow remains the Application process-orchestration domain
220
+
221
+ Public domain ownership remains:
222
+
223
+ ```text
224
+ Agent
225
+ Agent semantic execution + Agent Handoff
226
+
227
+ MultiAgent
228
+ durable framework-owned Orchestrator child coordination
229
+ durable Team queue/assignment/worker coordination
230
+ Runtime-only convenience fan-out outside a durable parent
231
+
232
+ Workflow
233
+ explicit Application-defined durable process/state-machine orchestration
234
+ durable ordering of Application-owned steps/effects when modeled by the app
235
+ ```
236
+
237
+ ### 15. Recovery contract clarifications
238
+
239
+ The normative [RC-01 through RC-05 contracts](../design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md)
240
+ apply to existing Orchestrator executions and Team executions:
241
+
242
+ - expose read-only status/result access and retained execution discovery;
243
+ - distinguish authoritative absence from read failure/unknown commit outcome;
244
+ - reconcile writes with the same reserved identities using existing Persistence
245
+ protocols, including Team-owned operation facts;
246
+ - verify declared definition id/version, registered slot wiring and reserved
247
+ owner/Agent/execution identities before continuation;
248
+ - preserve committed inputs/config, assignments and outcomes instead of
249
+ recalculating them with changed current code;
250
+ - distinguish observation loss/shutdown from semantic cancellation;
251
+ - stop new dispatch on accepted parent-run cancellation, reconcile already
252
+ admitted children using existing Agent cancellation and terminal barriers,
253
+ retain terminal outcomes and exact identities needed after restart;
254
+ - restrict cancellation to the current run's owned children, never unrelated
255
+ executions or later runs.
256
+
257
+ Stable version declarations do not prove Ruby code equivalence. Application code
258
+ must maintain declared compatibility; no Proc hash or generic registry is added.
259
+ Uncommitted replay-safe schedule/aggregate computation remains replayable.
260
+ No dedicated cancellation execution engine or callback recovery service is added.
261
+
262
+ ## Persistence changes
263
+
264
+ The durable root surface expands to include:
265
+
266
+ ```text
267
+ handoff_states
268
+ teams
269
+ team_executions
270
+ ```
271
+
272
+ Orchestrator continues to use Agent repositories.
273
+
274
+ No execution/team terminal-delivery pending index is added.
275
+
276
+ ## Required invariants
277
+
278
+ 1. Durable coordination is claimed only where a durable semantic root exists.
279
+ 2. Confirmed child/worker terminal work is never blindly rerun.
280
+ 3. Child/worker semantic work begins only after exact recoverable identity is
281
+ durably known.
282
+ 4. Orchestrator durable child coordination uses its existing AgentExecution.
283
+ 5. Standalone convenience fan-out is explicitly Runtime-only.
284
+ 6. Team has stable identity/execution and durable tasks/assignments/worker results.
285
+ 7. Scheduler and aggregator are replay-safe Application functions, not arbitrary
286
+ side-effect transaction boundaries.
287
+ 8. Callback/Task/FSMSession/Proc objects are never persisted.
288
+ 9. Workflow remains the appropriate domain for Application-defined durable process
289
+ orchestration.
290
+
291
+ ## Non-goals
292
+
293
+ This ADR does not:
294
+
295
+ - make standalone convenience fan-out restart-durable;
296
+ - make external Provider/Tool/Application effects exactly once;
297
+ - persist scheduler/aggregator Procs or callbacks;
298
+ - provide restart-spanning Team callback delivery;
299
+ - require worker history across TeamExecutions;
300
+ - add a generic global Agent class registry;
301
+ - turn MultiAgent into a public Workflow alias.
@@ -0,0 +1,176 @@
1
+ # Architecture Decision Records
2
+
3
+ This directory contains Phronomy Architecture Decision Records (ADRs).
4
+
5
+ The repository-wide architecture authority model is defined by
6
+ [`017-design-authority-and-adr-governance`](017-design-authority-and-adr-governance.md).
7
+ This index is the canonical navigation surface for ADR identity, status, and
8
+ supersession relationships.
9
+
10
+ ## Canonical ADR identity
11
+
12
+ The **canonical decision key** is the ADR filename basename, for example:
13
+
14
+ ```text
15
+ 012-canonical-execution-log-and-context-policy
16
+ ```
17
+
18
+ The three-digit numeric prefix is an ordering/display number. It is not, by
19
+ itself, a globally unique historical identifier because this repository
20
+ already contains two legacy ADRs numbered `011`.
21
+
22
+ Therefore:
23
+
24
+ - new or modified normative material SHOULD link to the ADR file or use its
25
+ full canonical decision key;
26
+ - the bare label `ADR-011` is ambiguous and MUST NOT be used to identify one
27
+ of the two legacy `011` decisions;
28
+ - existing historical text is not rewritten merely to normalize old
29
+ references.
30
+
31
+ ## Status and authority
32
+
33
+ ADR status has architecture meaning:
34
+
35
+ - **Accepted** — normative architecture intent unless explicitly superseded.
36
+ - **Amended** — normative architecture intent including its recorded
37
+ amendments.
38
+ - **Superseded** — retained as decision history; non-normative for the
39
+ superseded scope.
40
+ - **Proposed** — not normative until accepted.
41
+
42
+ An Accepted ADR can temporarily disagree with implementation reality. That is
43
+ an **architecture inconsistency**, not permission to silently treat whichever
44
+ artifact is newer as authoritative. The inconsistency must be tracked and
45
+ resolved explicitly.
46
+
47
+ ## ADR index
48
+
49
+ | Canonical decision key | Status | Normative now? | Supersession / note |
50
+ |---|---|---:|---|
51
+ | [`001-rubyllm-as-provider-layer`](001-rubyllm-as-provider-layer.md) | Superseded | No | Superseded by [`027-llm-adapter-provider-boundary`](027-llm-adapter-provider-boundary.md); historical RubyLLM adoption rationale retained. |
52
+ | [`002-workflow-context-immutability`](002-workflow-context-immutability.md) | Amended | Yes | `WorkflowContext#merge` remains new-instance semantics; direct generated field writers are EventLoop-owned guarded mutation APIs. |
53
+ | [`003-event-loop-singleton`](003-event-loop-singleton.md) | Accepted | Yes | Current until explicitly superseded/refined. |
54
+ | [`004-invoke-timeout-is-not-cancellation`](004-invoke-timeout-is-not-cancellation.md) | Superseded | No | Superseded by [`011-delegate-transport-policy-to-adapters`](011-delegate-transport-policy-to-adapters.md). |
55
+ | [`005-static-knowledge-class-level-cache`](005-static-knowledge-class-level-cache.md) | Superseded | No | Superseded by [`013-journal-backed-knowledge-as-context-candidates`](013-journal-backed-knowledge-as-context-candidates.md). |
56
+ | [`006-no-built-in-guardrails`](006-no-built-in-guardrails.md) | Superseded | No | Superseded by [`019-filter-contract-and-security-boundaries`](019-filter-contract-and-security-boundaries.md); historical minimal-built-in/Guardrail rationale retained. |
57
+ | [`007-mcp-is-beta-stability`](007-mcp-is-beta-stability.md) | Accepted | Yes | Current. |
58
+ | [`008-orchestrator-uses-os-threads`](008-orchestrator-uses-os-threads.md) | Superseded | No | Superseded by [`010-cooperative-first-concurrency`](010-cooperative-first-concurrency.md). |
59
+ | [`009-state-store-abstraction`](009-state-store-abstraction.md) | Superseded | No | Superseded by [`014-unified-persistence-durable-state`](014-unified-persistence-durable-state.md). |
60
+ | [`010-cooperative-first-concurrency`](010-cooperative-first-concurrency.md) | Accepted | Yes | Current until explicitly refined/superseded. |
61
+ | [`011-build-context-as-single-llm-input-authority`](011-build-context-as-single-llm-input-authority.md) | Superseded | No | Superseded by [`012-canonical-execution-log-and-context-policy`](012-canonical-execution-log-and-context-policy.md). |
62
+ | [`011-delegate-transport-policy-to-adapters`](011-delegate-transport-policy-to-adapters.md) | Accepted | Yes | Legacy duplicate numeric prefix; use the full canonical key. |
63
+ | [`012-canonical-execution-log-and-context-policy`](012-canonical-execution-log-and-context-policy.md) | Accepted | Yes | Current Journal / Manifest / Context authority. |
64
+ | [`013-journal-backed-knowledge-as-context-candidates`](013-journal-backed-knowledge-as-context-candidates.md) | Accepted | Yes | Current persistent Knowledge authority. |
65
+ | [`014-unified-persistence-durable-state`](014-unified-persistence-durable-state.md) | Accepted | Yes | Durable-backend and live-owner/no-reload intent remains current; live Agent execution mutation is refined by ADR-024, same-process Agent identity/admission ownership by ADR-025, and same-process Workflow admission/terminal-barrier ordering by ADR-026. Workflow identity terminology is superseded by ADR-020, generic `InvocationContext` / Agent correlation semantics by ADR-021, and concrete FSMSession/Agent-Tool routing identity by ADR-023. |
66
+ | [`015-tool-public-facade-and-rbs-boundary`](015-tool-public-facade-and-rbs-boundary.md) | Accepted | Yes | Current Tool façade / extension-SPI / RBS boundary. |
67
+ | [`016-semantic-multi-agent-handoff`](016-semantic-multi-agent-handoff.md) | Superseded | No | Superseded by [ADR-030](030-agent-handoff-domain-and-durable-responsibility.md), including Agent-domain ownership and exact Target recovery. |
68
+ | [`017-design-authority-and-adr-governance`](017-design-authority-and-adr-governance.md) | Accepted | Yes | Repository-wide architecture authority and ADR governance. |
69
+ | [`018-durability-guarantees-and-failure-model`](018-durability-guarantees-and-failure-model.md) | Accepted | Yes | Repository-wide durability/concurrency/external-effect guarantee vocabulary and F0-F4/X0 failure model. |
70
+ | [`019-filter-contract-and-security-boundaries`](019-filter-contract-and-security-boundaries.md) | Accepted | Yes | Current Filter transform/block and bounded PromptInjectionFilter/isolation boundaries; the follow-up review adds no fourth Context Filter call site and places semantic Context trust in Application ContextPolicy. |
71
+ | [`020-canonical-workflow-instance-identity`](020-canonical-workflow-instance-identity.md) | Accepted | Yes | Canonical logical/durable Workflow identity and CG-01 clean-break migration. |
72
+ | [`021-generic-agent-invocation-identity-removal`](021-generic-agent-invocation-identity-removal.md) | Accepted | Yes | Removes generic Agent/InvocationContext identity and canonical Journal `correlation_id`; CG-02 is closed, with targeted legacy durable-key read compatibility and no eager rewrite. |
73
+ | [`022-agent-execution-parent-identity-and-runtime-routing-boundary`](022-agent-execution-parent-identity-and-runtime-routing-boundary.md) | Accepted | Yes | Canonicalizes Agent-owned Tool/approval logical parent as `execution_id`; CG-03a is reconciled, ADR-023 supplies incarnation routing, and ADR-024 supplies EventLoop result/live-state authority. |
74
+ | [`023-fsm-session-incarnation-identity-and-routing`](023-fsm-session-incarnation-identity-and-routing.md) | Accepted | Yes | FSMSession-owned incarnation identity, session-local Agent/Tool/Multi-Agent routing, and stale-target drop remain current. Its transitional Workflow identity-reservation/admission bridge is superseded by ADR-026; Agent result authority is completed by ADR-024. |
75
+ | [`024-event-loop-single-writer-agent-runtime`](024-event-loop-single-writer-agent-runtime.md) | Accepted | Yes | EventLoop is the single writer of Phronomy-managed live Agent execution state; removes Activation/ActivationRegistry and defines operation-specific Offload result application with current FSM + semantic-ID authority. |
76
+ | [`025-process-local-agent-ownership-and-runtime-admission`](025-process-local-agent-ownership-and-runtime-admission.md) | Accepted | Yes | One mutable live Agent owner per `agent_id` per Runtime; EventLoop is the primary same-process top-level admission authority while Persistence admission remains durable defense. |
77
+ | [`026-workflow-runtime-admission-and-durable-terminal-barrier`](026-workflow-runtime-admission-and-durable-terminal-barrier.md) | Accepted | Yes | EventLoop-owned opaque Workflow admission owner, admission-before-hydration ordering, and FSMSession-integrated durable terminal save barrier with fail-closed uncertain outcomes. |
78
+ | [`027-llm-adapter-provider-boundary`](027-llm-adapter-provider-boundary.md) | Accepted | Yes | Phronomy-owned Provider-call extension boundary; RubyLLM is the default adapter/integration while current input materialization remains RubyLLM-specific. |
79
+ | [`028-preparing-recovery-replay-contract`](028-preparing-recovery-replay-contract.md) | Accepted | Yes | Adds replay-safe same-`execution_id` recovery for durably admitted Agent `:preparing` executions when replayability is durably established; unsupported Runtime-only dependencies fail closed. |
80
+ | [`029-semantic-completion-and-application-effect-boundary`](029-semantic-completion-and-application-effect-boundary.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
81
+ | [`030-agent-handoff-domain-and-durable-responsibility`](030-agent-handoff-domain-and-durable-responsibility.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
82
+ | [`031-durable-multi-agent-coordination`](031-durable-multi-agent-coordination.md) | Accepted | Yes | V2 revision 2; framework semantic coordination and Application effect boundary. |
83
+
84
+ ## Legacy duplicate `011`
85
+
86
+ The repository intentionally preserves both legacy files:
87
+
88
+ ```text
89
+ 011-build-context-as-single-llm-input-authority
90
+ 011-delegate-transport-policy-to-adapters
91
+ ```
92
+
93
+ They are different decisions. The first is superseded by ADR-012; the second
94
+ remains Accepted.
95
+
96
+ They MUST NOT be silently renumbered. Their filenames are stable historical
97
+ decision keys. New decisions may not introduce another duplicate numeric
98
+ prefix.
99
+
100
+ ## Allocating a new ADR identifier
101
+
102
+ For a new ADR:
103
+
104
+ 1. inspect all `NNN-*.md` files in this directory;
105
+ 2. allocate `max(existing numeric prefix) + 1`;
106
+ 3. format the number with three decimal digits;
107
+ 4. never fill an old gap and never reuse an existing prefix;
108
+ 5. if two unmerged changes select the same number, the change merged later
109
+ rebases and renumbers **only its new, not-yet-historical ADR**;
110
+ 6. add the ADR to this index in the same change.
111
+
112
+ Existing ADRs are not renumbered merely because a numbering defect is later
113
+ discovered. `016-semantic-multi-agent-handoff` is therefore preserved as-is.
114
+ Under this rule the Design Authority decision is ADR-017.
115
+
116
+ ## Superseding or amending a decision
117
+
118
+ Do not rewrite historical rationale into a fictional current history.
119
+
120
+ When superseding an ADR:
121
+
122
+ - add a new decision describing the new architecture;
123
+ - update the old ADR's status/supersession note only as needed;
124
+ - preserve the old rationale;
125
+ - update this index in the same change;
126
+ - use canonical decision keys/links where a numeric label would be ambiguous.
127
+
128
+ Amendments are appropriate only when the original decision remains the same
129
+ decision and the amendment can be understood without erasing the historical
130
+ rationale. Materially different architecture should normally be a new ADR.
131
+
132
+ ## Architecture inconsistency process
133
+
134
+ Architecture intent, public contract, and implementation reality are separate
135
+ authority domains. If they disagree, do not resolve the conflict by recency.
136
+
137
+ An unresolved architecture inconsistency must be recorded in the active
138
+ repository work item (normally a GitHub issue or PR) with at least:
139
+
140
+ ```text
141
+ Concern
142
+ Normative authority
143
+ Implementation / contract reality
144
+ Conflict
145
+ Resolution dependency
146
+ Status: OPEN | DEFERRED | RESOLVING | RESOLVED
147
+ Final resolution
148
+ ```
149
+
150
+ Existing Workstream carry-forward (`CF-*`) and architecture-inconsistency
151
+ (`AI-*`) registers are discovery/planning evidence, not normative architecture.
152
+ During the current reconciliation program their unresolved contents are
153
+ consolidated into named Architecture Change Sets (ACS) and Compatibility Gates
154
+ (CG). A repository change that resolves such an item should identify the
155
+ corresponding ACS/CG in its PR/commit rationale.
156
+
157
+ A legacy carry-forward proposition is closed only by one of:
158
+
159
+ - adoption into current source/public contract/current documentation;
160
+ - an Accepted ADR;
161
+ - explicit rejection/non-carry disposition; or
162
+ - an open repository work item when the resolution is intentionally deferred.
163
+
164
+ Working registers must not be copied wholesale into current architecture
165
+ documentation as if they were normative decisions.
166
+
167
+ ## Relationship to explanatory architecture documentation
168
+
169
+ ADRs record normative decisions. Explanatory architecture documents describe
170
+ the current reconciled system but do not supersede ADRs merely by being newer.
171
+
172
+ Current explanatory architecture starts at
173
+ [`docs/architecture.md`](../architecture.md). Non-current design snapshots are
174
+ segregated under `docs/archive/design/` and are non-normative. Explanatory
175
+ architecture documents describe the reconciled current system but do not
176
+ supersede ADRs merely by being newer.
@@ -0,0 +1,33 @@
1
+ # V2 revision 2 — 改訂内容
2
+
3
+ 更新日: 2026-09-06 / 状態: Accepted
4
+
5
+ ## 合意反映
6
+
7
+ | 項目 | 今回の修正 |
8
+ |---|---|
9
+ | RC-01 結果参照 | exact実行IDで状態・結果を読み取る契約と、ID受領前の停止に備えたownerからの候補発見を追加 |
10
+ | RC-02 保存成否不明 | 正常な不存在、read障害、CAS競合、commit成否不明を区別。同じ予約済みidentityで照合 |
11
+ | RC-03 wiring互換性 | 定義id/version・slot・graph・Persistence境界の最低照合と、確定済みfactの優先を明記 |
12
+ | RC-04 cancellation | 観測終了/shutdownとsemantic cancelを区別。子の状態別処理、競合、restart後の再発見を明記 |
13
+ | RC-05 保証表現 | 確定outcome再利用・同一identity復旧・外部成否不明は既存Recovery、に統一 |
14
+
15
+ ADR-029/030/031、実装設計、責務境界レビュー、READMEへ対応する規範的記述を反映した。
16
+ 詳細契約と検証条件はRECOVERY_CONTRACT_CLARIFICATIONS.mdにまとめ、資料間で参照する。
17
+ 承認前のProposed表記をAcceptedへ更新した。新機能の再承認を要求しない。
18
+
19
+ ## 実装状態の訂正
20
+
21
+ 引き継ぎ文書の旧実装件数・静的検証成功は、前セッションの報告として残す。
22
+ この分岐先で実装を再検証した事実にはしない。現在取得できたのは設計資料と引き継ぎ文書であり、
23
+ 旧overlay/apply.py/APPLY.sh/VERIFY.shは未取得。再開手順も実ファイルの回収から始める形に更新した。
24
+
25
+ ## 今回実施した確認
26
+
27
+ - 対象資料の承認状態、baseline、相互参照の整合確認。
28
+ - 旧い「未承認のため実装停止」表現と、外部効果のexactly-onceに読める保証表現の修正。
29
+ - RC-01〜05のADR・実装設計・検証条件への対応確認。
30
+ - ZIP構成、全文書のSHA256SUMS、ZIP/引き継ぎ文書の外部SHA256の検証。
31
+
32
+ 対象repositoryのコード変更・RSpec実行は行っていない。
33
+ API名や例外名は未確認のものを作らず、baselineへの対応付けを実装前の必須作業とした。