phronomy 0.23.0 → 0.24.1
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.
- checksums.yaml +4 -4
- data/.mutant.yml +2 -2
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +2 -2
- data/README.md +1 -1
- data/docs/architecture/multi-agent-handoff.md +35 -40
- data/docs/architecture/persistence.md +19 -8
- data/docs/architecture.md +8 -1
- data/docs/decisions/016-semantic-multi-agent-handoff.md +3 -1
- data/docs/decisions/028-preparing-recovery-replay-contract.md +106 -0
- data/docs/decisions/029-semantic-completion-and-application-effect-boundary.md +220 -0
- data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +235 -0
- data/docs/decisions/031-durable-multi-agent-coordination.md +301 -0
- data/docs/decisions/README.md +5 -1
- data/docs/design/durable-semantic-coordination/CHANGELOG_V2_REVISION_2.md +33 -0
- data/docs/design/durable-semantic-coordination/CONTINUATION_DECISION_REFACTOR.md +191 -0
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +862 -0
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +106 -0
- data/docs/design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md +179 -0
- data/docs/design/durable-semantic-coordination/RESPONSIBILITY_BOUNDARY_REVIEW.md +302 -0
- data/docs/features.md +35 -1
- data/docs/migrations/durable-semantic-coordination-v2.md +65 -0
- data/docs/persistence-backends.md +42 -3
- data/lib/phronomy/agent/agent_execution.rb +2 -2
- data/lib/phronomy/agent/agent_invocation.rb +1 -1
- data/lib/phronomy/agent/async_event_api.rb +18 -1
- data/lib/phronomy/agent/base.rb +28 -0
- data/lib/phronomy/agent/context_assembler.rb +1 -1
- data/lib/phronomy/agent/exact_execution.rb +153 -0
- data/lib/phronomy/agent/execution_cancellation.rb +25 -0
- data/lib/phronomy/agent/execution_coordinator.rb +484 -27
- data/lib/phronomy/{multi_agent → agent}/handoff.rb +4 -4
- data/lib/phronomy/{multi_agent → agent}/handoff_capability_factory.rb +3 -45
- data/lib/phronomy/{multi_agent → agent}/handoff_context.rb +26 -1
- data/lib/phronomy/{multi_agent/execution_coordinator.rb → agent/handoff_execution_coordinator.rb} +32 -5
- data/lib/phronomy/{multi_agent → agent}/handoff_policy.rb +7 -1
- data/lib/phronomy/{multi_agent → agent}/handoff_projection.rb +18 -2
- data/lib/phronomy/{multi_agent → agent}/handoff_request.rb +2 -2
- data/lib/phronomy/agent/handoff_runner.rb +178 -0
- data/lib/phronomy/agent/handoff_state.rb +43 -0
- data/lib/phronomy/agent/recovery_coordinator/continuation.rb +114 -211
- data/lib/phronomy/agent/recovery_coordinator/installation.rb +84 -130
- data/lib/phronomy/agent/recovery_coordinator/resolution.rb +76 -200
- data/lib/phronomy/agent/recovery_coordinator.rb +11 -5
- data/lib/phronomy/agent/recovery_support.rb +15 -23
- data/lib/phronomy/agent/ruby_llm_materializer.rb +2 -8
- data/lib/phronomy/agent/tool_invocation.rb +4 -2
- data/lib/phronomy/engine/runtime/team_ownership_registry.rb +77 -0
- data/lib/phronomy/engine/runtime.rb +16 -1
- data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +134 -0
- data/lib/phronomy/multi_agent/orchestrator.rb +59 -11
- data/lib/phronomy/multi_agent/team_coordinator.rb +473 -125
- data/lib/phronomy/multi_agent/team_execution.rb +44 -0
- data/lib/phronomy/multi_agent/team_root.rb +41 -0
- data/lib/phronomy/persistence/durable_codec.rb +60 -0
- data/lib/phronomy/persistence/in_memory.rb +264 -2
- data/lib/phronomy/persistence/repository_facades.rb +221 -2
- data/lib/phronomy/persistence.rb +95 -1
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +1 -0
- data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +137 -0
- data/lib/phronomy/testing/persistence_contract.rb +5 -0
- data/lib/phronomy/tools/agent.rb +1 -1
- data/lib/phronomy/version.rb +1 -1
- data/scripts/api_snapshot.rb +3 -3
- data/sig/phronomy/handoff.rbs +41 -0
- data/sig/phronomy/multi_agent.rbs +28 -32
- data/sig/phronomy/persistence.rbs +64 -3
- metadata +44 -12
- data/lib/phronomy/multi_agent/coordination_state.rb +0 -18
- data/lib/phronomy/multi_agent/coordinator.rb +0 -154
- data/lib/phronomy/multi_agent/runner.rb +0 -98
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# ADR-030: Agent Handoff Domain and Durable Responsibility
|
|
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
|
+
## Partially supersedes
|
|
15
|
+
|
|
16
|
+
`016-semantic-multi-agent-handoff` for:
|
|
17
|
+
|
|
18
|
+
- namespace/domain placement of Handoff;
|
|
19
|
+
- Runtime-local-only active responsibility;
|
|
20
|
+
- allowance for independent Source/Target Persistence domains in the durable
|
|
21
|
+
Handoff path; and
|
|
22
|
+
- the public Handoff Runner namespace.
|
|
23
|
+
|
|
24
|
+
ADR-016 remains the historical rationale and remains authoritative for the
|
|
25
|
+
Source-to-Target semantic transfer model, HandoffPolicy category semantics,
|
|
26
|
+
Context dependency grouping, immutable transferred Context, Target ContextPolicy
|
|
27
|
+
ownership, and provenance rules except where this ADR explicitly changes them.
|
|
28
|
+
|
|
29
|
+
## Context
|
|
30
|
+
|
|
31
|
+
ADR-016 intentionally made active Handoff responsibility Runtime-local. Process
|
|
32
|
+
reset therefore restarted responsibility at the main Agent.
|
|
33
|
+
|
|
34
|
+
That behavior is insufficient for a framework-owned Handoff abstraction once the
|
|
35
|
+
Source execution has durably committed `:handed_off`: process loss must not force
|
|
36
|
+
Source semantic work to run again merely to rediscover the Target.
|
|
37
|
+
|
|
38
|
+
This is a framework semantic-routing concern, not an Application callback concern.
|
|
39
|
+
ADR-029 therefore does not make Handoff durability depend on restart-spanning
|
|
40
|
+
notification delivery.
|
|
41
|
+
|
|
42
|
+
## Decision
|
|
43
|
+
|
|
44
|
+
### 1. Handoff moves to the Agent domain
|
|
45
|
+
|
|
46
|
+
Public types move as a clean break:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
Phronomy::MultiAgent::Handoff
|
|
50
|
+
-> Phronomy::Agent::Handoff
|
|
51
|
+
|
|
52
|
+
Phronomy::MultiAgent::HandoffPolicy
|
|
53
|
+
-> Phronomy::Agent::HandoffPolicy
|
|
54
|
+
|
|
55
|
+
Phronomy::MultiAgent::Runner
|
|
56
|
+
-> Phronomy::Agent::HandoffRunner
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Handoff-specific private types move under the Agent Handoff implementation
|
|
60
|
+
boundary.
|
|
61
|
+
|
|
62
|
+
No compatibility alias is required by this ADR.
|
|
63
|
+
|
|
64
|
+
### 2. `main_agent.agent_id` is the durable routing anchor
|
|
65
|
+
|
|
66
|
+
No generic coordination/thread/session identity is introduced.
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
main_agent.agent_id
|
|
70
|
+
= durable Handoff routing anchor
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
One durable HandoffState is keyed by that identity.
|
|
74
|
+
|
|
75
|
+
### 3. Persistence adds `handoff_states`
|
|
76
|
+
|
|
77
|
+
The durable state contains semantic routing facts only:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
main_agent_id
|
|
81
|
+
handoff_revision
|
|
82
|
+
active_agent_id
|
|
83
|
+
active_handoff_context_ref
|
|
84
|
+
phase
|
|
85
|
+
pending_source_execution_id
|
|
86
|
+
pending_target_execution_id
|
|
87
|
+
created_at
|
|
88
|
+
updated_at
|
|
89
|
+
metadata
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
It never stores Agent instances, Agent classes, Procs, HandoffPolicy objects,
|
|
93
|
+
Tasks, FSMSessions or EventLoop routing state.
|
|
94
|
+
|
|
95
|
+
### 4. One durable Handoff graph uses one Persistence domain
|
|
96
|
+
|
|
97
|
+
The main/source/target Agents and HandoffState must use the same
|
|
98
|
+
`Phronomy::Persistence` transaction domain.
|
|
99
|
+
|
|
100
|
+
A graph requiring a distributed transaction across independent Persistence
|
|
101
|
+
domains is rejected before semantic work.
|
|
102
|
+
|
|
103
|
+
### 5. Source terminalization and responsibility transfer are one semantic transaction
|
|
104
|
+
|
|
105
|
+
When a Source chooses a valid Handoff, Phronomy:
|
|
106
|
+
|
|
107
|
+
1. resolves the current finalized Source Manifest;
|
|
108
|
+
2. applies HandoffPolicy projection;
|
|
109
|
+
3. materializes immutable HandoffContext;
|
|
110
|
+
4. reserves the exact Target `execution_id`;
|
|
111
|
+
5. commits Source `:handed_off` and HandoffState transfer atomically.
|
|
112
|
+
|
|
113
|
+
The transaction records at least:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
Source AgentExecution -> :handed_off
|
|
117
|
+
Source AgentRoot terminal/idle revision
|
|
118
|
+
Source Journal audit facts
|
|
119
|
+
HandoffContext content reference
|
|
120
|
+
HandoffState.active_agent_id -> Target
|
|
121
|
+
HandoffState.active_handoff_context_ref -> transferred Context
|
|
122
|
+
HandoffState.phase -> target_pending
|
|
123
|
+
HandoffState.pending_source_execution_id -> Source execution_id
|
|
124
|
+
HandoffState.pending_target_execution_id -> reserved Target execution_id
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
There is no terminal callback-delivery descriptor in this transaction.
|
|
128
|
+
|
|
129
|
+
### 6. Target execution identity is reserved before Target semantic work
|
|
130
|
+
|
|
131
|
+
Recovery uses the exact reserved Target `execution_id`:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
authoritatively absent after a successful read
|
|
135
|
+
-> establish that exact reserved execution only after admission is confirmed
|
|
136
|
+
|
|
137
|
+
nonterminal
|
|
138
|
+
-> recover that exact execution
|
|
139
|
+
|
|
140
|
+
terminal
|
|
141
|
+
-> consume its durable outcome; never create a replacement execution
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The execution ID is semantic Agent identity, not Runtime FSMSession identity.
|
|
145
|
+
|
|
146
|
+
### 7. Active responsibility survives later turns and process loss
|
|
147
|
+
|
|
148
|
+
When a Handoff turn ends normally at Target B, `active_agent_id` remains B.
|
|
149
|
+
|
|
150
|
+
The next HandoffRunner turn starts at B.
|
|
151
|
+
|
|
152
|
+
After process reset, compatible HandoffRunner wiring loads the same HandoffState
|
|
153
|
+
and again starts/resumes from B rather than reverting to the original main Agent.
|
|
154
|
+
|
|
155
|
+
### 8. Multi-hop updates the same HandoffState
|
|
156
|
+
|
|
157
|
+
A -> B -> C updates the original main-Agent-anchored HandoffState.
|
|
158
|
+
|
|
159
|
+
No nested generic coordination IDs are created.
|
|
160
|
+
|
|
161
|
+
### 9. Runtime graph/Policy wiring is Application code
|
|
162
|
+
|
|
163
|
+
HandoffRunner requires the current Application-supplied Handoff graph and Policies
|
|
164
|
+
to reconstruct Runtime behavior.
|
|
165
|
+
|
|
166
|
+
Those Ruby objects are never persisted.
|
|
167
|
+
|
|
168
|
+
If required wiring is absent or incompatible, recovery fails closed instead of:
|
|
169
|
+
|
|
170
|
+
- reverting to main Agent;
|
|
171
|
+
- inventing a graph;
|
|
172
|
+
- blindly replaying Source work.
|
|
173
|
+
|
|
174
|
+
### 10. HandoffContext is durably materializable but not adopted automatically
|
|
175
|
+
|
|
176
|
+
The canonical immutable HandoffContext value is stored in ContentStore and
|
|
177
|
+
referenced by HandoffState/execution metadata.
|
|
178
|
+
|
|
179
|
+
Transferred material remains request-scoped Target Context unless Target
|
|
180
|
+
execution creates its own canonical Journal/Knowledge facts.
|
|
181
|
+
|
|
182
|
+
### 11. Local Application events are Runtime-only
|
|
183
|
+
|
|
184
|
+
A Source may emit a same-process `:handoff` event.
|
|
185
|
+
|
|
186
|
+
That event is not durable routing authority and is not redelivered after restart.
|
|
187
|
+
|
|
188
|
+
Handoff coordination correctness depends only on durable semantic routing facts.
|
|
189
|
+
|
|
190
|
+
### 12. Recovery evidence, compatibility and cancellation
|
|
191
|
+
|
|
192
|
+
Apply [RC-01 through RC-05](../design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md).
|
|
193
|
+
Read failures/unknown commit outcomes must not be treated as Target absence.
|
|
194
|
+
Readback reconciles the same reserved execution and transfer facts; admission
|
|
195
|
+
races use existing atomic admission/CAS, never a replacement Target ID.
|
|
196
|
+
|
|
197
|
+
Before continuation, check main/active/Target identities, current required graph
|
|
198
|
+
connections, declared definition compatibility and the same Persistence instance.
|
|
199
|
+
Absent an existing explicit migration/compatibility contract, definition id/version
|
|
200
|
+
must match. Current wiring never reprojects committed HandoffContext. Proc/code
|
|
201
|
+
hashing and automatic semantic code-compatibility detection are not introduced.
|
|
202
|
+
|
|
203
|
+
Result reads follow the specified run's recorded Target, not an unrelated later
|
|
204
|
+
turn's latest active result. Continuation wiring is not required merely to read
|
|
205
|
+
stored status/canonical results.
|
|
206
|
+
|
|
207
|
+
After transfer commit the Source remains handed_off. Observation loss or cancel
|
|
208
|
+
must not roll active responsibility back to main. An explicit cancellation of the
|
|
209
|
+
current turn is routed to that turn's exact reserved Target under existing Agent
|
|
210
|
+
cancellation rules; it does not cancel unrelated/later executions. Preserve the
|
|
211
|
+
facts needed to reconcile cancellation/admission races and process loss.
|
|
212
|
+
|
|
213
|
+
## Required invariants
|
|
214
|
+
|
|
215
|
+
1. Handoff is an Agent-domain capability.
|
|
216
|
+
2. `main_agent.agent_id` is the durable routing anchor.
|
|
217
|
+
3. Active responsibility survives process loss.
|
|
218
|
+
4. Source `:handed_off` and durable responsibility transfer cannot diverge.
|
|
219
|
+
5. Target semantic work never starts without a recoverable reserved execution ID.
|
|
220
|
+
6. A committed Source Handoff is never blindly replayed.
|
|
221
|
+
7. Recovery reconstructs fresh Runtime objects.
|
|
222
|
+
8. Graph/Policy Ruby objects are supplied by Application code, not persisted.
|
|
223
|
+
9. All durable graph participants share one Persistence domain.
|
|
224
|
+
10. Application callback delivery is not part of Handoff durability.
|
|
225
|
+
|
|
226
|
+
## Non-goals
|
|
227
|
+
|
|
228
|
+
This ADR does not:
|
|
229
|
+
|
|
230
|
+
- make arbitrary external effects exactly once;
|
|
231
|
+
- provide restart-spanning local Handoff callback delivery;
|
|
232
|
+
- add distributed transactions across Persistence domains;
|
|
233
|
+
- add generic coordination/session/thread identity;
|
|
234
|
+
- persist HandoffPolicy/Application code;
|
|
235
|
+
- merge Source and Target Agent state.
|
|
@@ -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.
|
data/docs/decisions/README.md
CHANGED
|
@@ -64,7 +64,7 @@ resolved explicitly.
|
|
|
64
64
|
| [`013-journal-backed-knowledge-as-context-candidates`](013-journal-backed-knowledge-as-context-candidates.md) | Accepted | Yes | Current persistent Knowledge authority. |
|
|
65
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
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) |
|
|
67
|
+
| [`016-semantic-multi-agent-handoff`](016-semantic-multi-agent-handoff.md) | Superseded | No | Superseded by [ADR-030](030-agent-handoff-domain-and-durable-responsibility.md), including Agent-domain ownership and exact Target recovery. |
|
|
68
68
|
| [`017-design-authority-and-adr-governance`](017-design-authority-and-adr-governance.md) | Accepted | Yes | Repository-wide architecture authority and ADR governance. |
|
|
69
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
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. |
|
|
@@ -76,6 +76,10 @@ resolved explicitly.
|
|
|
76
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
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
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. |
|
|
79
83
|
|
|
80
84
|
## Legacy duplicate `011`
|
|
81
85
|
|
|
@@ -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への対応付けを実装前の必須作業とした。
|