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,862 @@
|
|
|
1
|
+
# Phronomy Durable Semantic Coordination — Implementation Design V2
|
|
2
|
+
|
|
3
|
+
## 0. Status and authority
|
|
4
|
+
|
|
5
|
+
**Accepted implementation design — V2 revision 2 (2026-09-06).**
|
|
6
|
+
|
|
7
|
+
This revision incorporates the user-approved five recovery-contract clarifications.
|
|
8
|
+
The implementation targets the fixed baseline below. Measured validation and
|
|
9
|
+
API/SPI mappings are recorded in [IMPLEMENTATION_REPORT.md](IMPLEMENTATION_REPORT.md).
|
|
10
|
+
|
|
11
|
+
Baseline:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
repository: Raizo-TCS/phronomy
|
|
15
|
+
commit: 5472116cd99a63ec27875024c955ea82be612d6b
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This V2 design supersedes the earlier "Complete Durability" working implementation
|
|
19
|
+
plan.
|
|
20
|
+
|
|
21
|
+
The V2 boundary and this revision are approved. No renewed design approval is
|
|
22
|
+
required. Implementation resumes only from verified baseline and source artifacts;
|
|
23
|
+
Stop Conditions still apply.
|
|
24
|
+
|
|
25
|
+
## 1. Design objective
|
|
26
|
+
|
|
27
|
+
The implementation target is:
|
|
28
|
+
|
|
29
|
+
> Preserve Phronomy-owned semantic execution/coordination progress across
|
|
30
|
+
> process/runtime loss, without blindly repeating confirmed semantic work.
|
|
31
|
+
|
|
32
|
+
It is **not**:
|
|
33
|
+
|
|
34
|
+
> make every callback, Task, convenience API or external side effect durable.
|
|
35
|
+
|
|
36
|
+
## 2. Responsibility boundary
|
|
37
|
+
|
|
38
|
+
### 2.1 Phronomy durable authority
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
AgentExecution semantic facts
|
|
42
|
+
Handoff routing state
|
|
43
|
+
Orchestrator child coordination attached to an existing AgentExecution
|
|
44
|
+
TeamRoot / TeamExecution
|
|
45
|
+
Team tasks, assignments, reserved worker identities and worker outcomes
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2.2 Runtime/Application authority
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
on_event callbacks
|
|
52
|
+
Tasks
|
|
53
|
+
stream callbacks
|
|
54
|
+
scheduler/aggregator Proc objects
|
|
55
|
+
FSMSessions
|
|
56
|
+
EventLoop routing/admission tokens
|
|
57
|
+
standalone convenience fan-out state
|
|
58
|
+
email/webhook/database effects
|
|
59
|
+
external side-effect idempotency
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 3. Cross-cutting invariants
|
|
63
|
+
|
|
64
|
+
### 3.1 Persist facts, never Runtime objects
|
|
65
|
+
|
|
66
|
+
Never persist:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
FSMSession / fsm_session_id
|
|
70
|
+
Task
|
|
71
|
+
callback / Proc
|
|
72
|
+
Ruby Class object
|
|
73
|
+
AgentInvocation
|
|
74
|
+
EventSink
|
|
75
|
+
EventLoop queue/admission token
|
|
76
|
+
Mutex / Thread / Fiber
|
|
77
|
+
CancellationToken object
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3.2 EventLoop remains the live-state writer
|
|
81
|
+
|
|
82
|
+
New durable operations follow:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
EventLoop
|
|
86
|
+
-> immutable operation command
|
|
87
|
+
Offload
|
|
88
|
+
-> blocking Persistence transaction/reconciliation
|
|
89
|
+
EventLoop
|
|
90
|
+
-> authority validation + live apply + next Runtime action
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3.3 Confirmed semantic work is not replayed
|
|
94
|
+
|
|
95
|
+
Use durable evidence before deciding to invoke:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
Provider/Tool recovery rules already owned by Agent
|
|
99
|
+
Handoff Source/Target
|
|
100
|
+
Orchestrator child AgentExecution
|
|
101
|
+
Team worker AgentExecution
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 3.4 Exact recovery does not mean exactly-once external effects
|
|
105
|
+
|
|
106
|
+
Reuse confirmed durable outcomes. Recover unfinished work under the same semantic
|
|
107
|
+
execution identity. Resolve unknown Provider/Tool effects through existing Agent
|
|
108
|
+
Recovery. A successful authoritative absence read plus confirmed admission is
|
|
109
|
+
required before starting an absent reserved execution. Read/commit errors do not
|
|
110
|
+
establish absence; preserve IDs and reconcile using existing Persistence rules.
|
|
111
|
+
|
|
112
|
+
### 3.5 Application effects are not promoted into framework transactions
|
|
113
|
+
|
|
114
|
+
Do not introduce durable protocols merely to retry:
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
on_event
|
|
118
|
+
stream callback
|
|
119
|
+
email/webhook
|
|
120
|
+
arbitrary DB side effect
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
When an Application needs those effects to survive restart, it owns the durable
|
|
124
|
+
mechanism.
|
|
125
|
+
|
|
126
|
+
## 4. Persistence SPI
|
|
127
|
+
|
|
128
|
+
### 4.1 Root surface
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
contents
|
|
132
|
+
agents
|
|
133
|
+
journals
|
|
134
|
+
executions
|
|
135
|
+
workflow_states
|
|
136
|
+
handoff_states
|
|
137
|
+
teams
|
|
138
|
+
team_executions
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
All record repositories participate in the same `atomic_all` transaction domain.
|
|
142
|
+
|
|
143
|
+
### 4.2 Removed from the previous design
|
|
144
|
+
|
|
145
|
+
Do **not** add:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
executions.list_delivery_pending
|
|
149
|
+
execution delivery_pending raw metadata/index
|
|
150
|
+
team_executions.list_delivery_pending
|
|
151
|
+
Team/Agent terminal-delivery descriptors
|
|
152
|
+
callback ACK revisions
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 4.3 `handoff_states`
|
|
156
|
+
|
|
157
|
+
Purpose-specific repository:
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
load(main_agent_id)
|
|
161
|
+
save(
|
|
162
|
+
main_agent_id,
|
|
163
|
+
expected_revision:,
|
|
164
|
+
next_revision:,
|
|
165
|
+
active_agent_id:,
|
|
166
|
+
record:
|
|
167
|
+
)
|
|
168
|
+
delete(main_agent_id, expected_revision:)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Current-format record type:
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
phronomy.handoff_state 0.1
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 4.4 `teams`
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
create(root)
|
|
181
|
+
load(team_id)
|
|
182
|
+
save(team_id, expected_revision:, root:)
|
|
183
|
+
delete(team_id)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Record type:
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
phronomy.team_root 0.1
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 4.5 `team_executions`
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
create_active(execution)
|
|
196
|
+
load(team_execution_id)
|
|
197
|
+
save(team_execution_id, expected_revision:, execution:)
|
|
198
|
+
list_active(team_id)
|
|
199
|
+
delete(team_execution_id)
|
|
200
|
+
delete_for_team(team_id)
|
|
201
|
+
assert_idle!(team_id)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Raw metadata includes only identity/revision/active indexing needed by backend.
|
|
205
|
+
|
|
206
|
+
No delivery-pending metadata.
|
|
207
|
+
|
|
208
|
+
Record type:
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
phronomy.team_execution 0.1
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 5. Agent terminal behavior
|
|
215
|
+
|
|
216
|
+
No new terminal-delivery subsystem.
|
|
217
|
+
|
|
218
|
+
Terminal flow remains:
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
semantic terminal operation
|
|
222
|
+
-> durable terminal transaction
|
|
223
|
+
-> EventLoop apply/release admission
|
|
224
|
+
-> optional same-process callback
|
|
225
|
+
-> same-process Task settlement
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Process loss after durable terminal commit may lose callback/Task observation.
|
|
229
|
+
|
|
230
|
+
Recovery must never replay terminal semantic work merely to reproduce those
|
|
231
|
+
observations.
|
|
232
|
+
|
|
233
|
+
No `:completing` status.
|
|
234
|
+
|
|
235
|
+
## 6. Handoff implementation
|
|
236
|
+
|
|
237
|
+
### 6.1 Public clean break
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
Phronomy::Agent::Handoff
|
|
241
|
+
Phronomy::Agent::HandoffPolicy
|
|
242
|
+
Phronomy::Agent::HandoffRunner
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Old `Phronomy::MultiAgent` Handoff public constants are removed, with no aliases
|
|
246
|
+
unless separately approved.
|
|
247
|
+
|
|
248
|
+
### 6.2 HandoffState
|
|
249
|
+
|
|
250
|
+
Fields:
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
main_agent_id
|
|
254
|
+
handoff_revision
|
|
255
|
+
active_agent_id
|
|
256
|
+
active_handoff_context_ref
|
|
257
|
+
phase: stable | target_pending | target_active
|
|
258
|
+
pending_source_execution_id
|
|
259
|
+
pending_target_execution_id
|
|
260
|
+
created_at
|
|
261
|
+
updated_at
|
|
262
|
+
metadata
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 6.3 HandoffContext
|
|
266
|
+
|
|
267
|
+
Canonical `to_h/from_h` for:
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
HandoffContext
|
|
271
|
+
HandoffContext::Item
|
|
272
|
+
HandoffContext::Provenance
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Store via ContentStore. Do not adopt into Target Journal/Knowledge automatically.
|
|
276
|
+
|
|
277
|
+
### 6.4 Source transfer transaction
|
|
278
|
+
|
|
279
|
+
Capture a value-only Handoff commit specification from current Runtime wiring:
|
|
280
|
+
|
|
281
|
+
```text
|
|
282
|
+
main_agent_id
|
|
283
|
+
target_agent_id
|
|
284
|
+
reserved_target_execution_id
|
|
285
|
+
responsibility
|
|
286
|
+
selection_intent
|
|
287
|
+
handoff_policy_value
|
|
288
|
+
source_manifest_ref
|
|
289
|
+
expected_handoff_revision
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Transaction:
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
Source Journal terminal/audit facts
|
|
296
|
+
Source AgentExecution -> handed_off
|
|
297
|
+
Source AgentRoot
|
|
298
|
+
HandoffContext content
|
|
299
|
+
HandoffState -> target_pending + exact Target execution reservation
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
No callback delivery state.
|
|
303
|
+
|
|
304
|
+
### 6.5 Target reconciliation
|
|
305
|
+
|
|
306
|
+
For `pending_target_execution_id`:
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
Authoritative NotFound after a successful read
|
|
310
|
+
-> confirm current parent/owner/cancellation state
|
|
311
|
+
-> atomically admit exactly that execution ID before semantic work
|
|
312
|
+
|
|
313
|
+
active/nonterminal
|
|
314
|
+
-> recover the exact execution
|
|
315
|
+
-> stabilize target_active
|
|
316
|
+
|
|
317
|
+
terminal
|
|
318
|
+
-> consume durable outcome
|
|
319
|
+
-> stabilize HandoffState
|
|
320
|
+
-> never create replacement semantic work
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
On unknown transfer/admission/stabilization commit outcome, read back the same
|
|
324
|
+
reserved identities. A failed read is not NotFound. See RC-02.
|
|
325
|
+
|
|
326
|
+
### 6.6 Handoff-managed Agent recovery
|
|
327
|
+
|
|
328
|
+
Generic `Agent.load` may hydrate the Agent, but continuation requiring Handoff
|
|
329
|
+
graph wiring must wait for compatible `HandoffRunner`.
|
|
330
|
+
|
|
331
|
+
Do not persist graph/Policy Ruby objects.
|
|
332
|
+
|
|
333
|
+
### 6.7 Multi-hop
|
|
334
|
+
|
|
335
|
+
Every later transfer updates the same HandoffState keyed by original
|
|
336
|
+
`main_agent.agent_id`.
|
|
337
|
+
|
|
338
|
+
## 7. Orchestrator implementation
|
|
339
|
+
|
|
340
|
+
### 7.1 Durable scope
|
|
341
|
+
|
|
342
|
+
Durable child coordination exists only when there is an existing parent
|
|
343
|
+
Orchestrator AgentExecution.
|
|
344
|
+
|
|
345
|
+
Use:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
AgentExecution.metadata["multi_agent_coordination_ref"]
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
to reference an immutable coordination snapshot.
|
|
352
|
+
|
|
353
|
+
### 7.2 Coordination snapshot
|
|
354
|
+
|
|
355
|
+
```text
|
|
356
|
+
kind
|
|
357
|
+
phase
|
|
358
|
+
max_concurrency
|
|
359
|
+
on_error
|
|
360
|
+
children[]
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Child:
|
|
364
|
+
|
|
365
|
+
```text
|
|
366
|
+
slot
|
|
367
|
+
agent_definition_id/version
|
|
368
|
+
agent_id
|
|
369
|
+
execution_id
|
|
370
|
+
input_ref
|
|
371
|
+
durable_config_ref
|
|
372
|
+
state: reserved | active | completed | failed | skipped
|
|
373
|
+
result_ref
|
|
374
|
+
error_ref
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 7.3 Child reservation
|
|
378
|
+
|
|
379
|
+
Before child semantic work:
|
|
380
|
+
|
|
381
|
+
```text
|
|
382
|
+
reserve agent_id
|
|
383
|
+
reserve execution_id
|
|
384
|
+
persist parent snapshot
|
|
385
|
+
then create/load child
|
|
386
|
+
then start exact reserved execution
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Child completion Task/callback is only a Runtime wake-up.
|
|
390
|
+
|
|
391
|
+
Parent reconciliation re-reads the exact child AgentExecution and persists the
|
|
392
|
+
authoritative child result/error before advancing the reconstructed FSM.
|
|
393
|
+
|
|
394
|
+
### 7.4 Stable child wiring
|
|
395
|
+
|
|
396
|
+
Durable child definitions are resolved from static/current Orchestrator wiring.
|
|
397
|
+
|
|
398
|
+
Do not persist Ruby Class handles. Apply RC-03 definition id/version and slot
|
|
399
|
+
compatibility checks; retain committed child inputs/config rather than current
|
|
400
|
+
defaults. Do not infer semantic code equivalence from matching versions.
|
|
401
|
+
|
|
402
|
+
### 7.5 Standalone convenience calls
|
|
403
|
+
|
|
404
|
+
Do not create synthetic AgentExecutions for:
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
orchestrator.dispatch_parallel(...)
|
|
408
|
+
orchestrator.dispatch_parallel_async(...)
|
|
409
|
+
orchestrator.fan_out(...)
|
|
410
|
+
orchestrator.fan_out_async(...)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
when invoked outside a parent Orchestrator AgentExecution.
|
|
414
|
+
|
|
415
|
+
These retain Runtime-only semantics.
|
|
416
|
+
|
|
417
|
+
This also means direct convenience calls do **not** need the durable-path static
|
|
418
|
+
child-definition restriction.
|
|
419
|
+
|
|
420
|
+
### 7.6 Durable fan-out usage
|
|
421
|
+
|
|
422
|
+
Applications requiring restart-durable fan-out use:
|
|
423
|
+
|
|
424
|
+
```text
|
|
425
|
+
Orchestrator Agent invocation + registered subagent Tool/wiring
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
or an explicit Workflow for application process orchestration.
|
|
429
|
+
|
|
430
|
+
## 8. TeamCoordinator implementation
|
|
431
|
+
|
|
432
|
+
### 8.1 Identity
|
|
433
|
+
|
|
434
|
+
Concrete Team class declares:
|
|
435
|
+
|
|
436
|
+
```ruby
|
|
437
|
+
team_definition id: "research-team", version: 1
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
One logical Team instance:
|
|
441
|
+
|
|
442
|
+
```text
|
|
443
|
+
team_id
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
One run:
|
|
447
|
+
|
|
448
|
+
```text
|
|
449
|
+
team_execution_id
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### 8.2 TeamRoot
|
|
453
|
+
|
|
454
|
+
```text
|
|
455
|
+
team_id
|
|
456
|
+
team_definition_id/version
|
|
457
|
+
team_revision
|
|
458
|
+
lifecycle_status
|
|
459
|
+
created_at/updated_at
|
|
460
|
+
metadata
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### 8.3 TeamExecution
|
|
464
|
+
|
|
465
|
+
Keep only semantic durable facts, for example:
|
|
466
|
+
|
|
467
|
+
```text
|
|
468
|
+
team_execution_id
|
|
469
|
+
team_id
|
|
470
|
+
execution_revision
|
|
471
|
+
status / phase
|
|
472
|
+
input_ref
|
|
473
|
+
tasks
|
|
474
|
+
workers
|
|
475
|
+
assignments
|
|
476
|
+
result_ref
|
|
477
|
+
error_ref
|
|
478
|
+
created_at/updated_at
|
|
479
|
+
metadata
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Do not include:
|
|
483
|
+
|
|
484
|
+
```text
|
|
485
|
+
terminal_delivery
|
|
486
|
+
aggregation started/unknown resolution state
|
|
487
|
+
callback state
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### 8.4 Stable task-generation coordinator Agent
|
|
491
|
+
|
|
492
|
+
Replace random per-invoke coordinator definition identity with stable definition
|
|
493
|
+
derived from Team class definition.
|
|
494
|
+
|
|
495
|
+
Coordinator Agent itself uses normal Agent durability/recovery.
|
|
496
|
+
|
|
497
|
+
### 8.5 Durable enqueue/finalize
|
|
498
|
+
|
|
499
|
+
`enqueue_task` writes canonical task records into TeamExecution. Authorized
|
|
500
|
+
framework operations in one saved Tool batch commit in Provider order in the same
|
|
501
|
+
Team transaction; `finalize` cannot overtake an earlier `enqueue_task`. The stable
|
|
502
|
+
Tool invocation IDs retain each operation result for exact reconciliation.
|
|
503
|
+
|
|
504
|
+
`finalize` marks task generation complete.
|
|
505
|
+
|
|
506
|
+
Once a task exists durably, recovery does not ask coordinator Agent to recreate it.
|
|
507
|
+
|
|
508
|
+
### 8.6 Worker assignment reservation
|
|
509
|
+
|
|
510
|
+
Before worker semantic execution:
|
|
511
|
+
|
|
512
|
+
```text
|
|
513
|
+
select available worker
|
|
514
|
+
reserve worker agent_id for TeamExecution slot
|
|
515
|
+
reserve exact worker execution_id
|
|
516
|
+
commit task -> worker assignment
|
|
517
|
+
then start/recover that exact execution
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### 8.7 Scheduler contract
|
|
521
|
+
|
|
522
|
+
`schedule` is Application code but must be replay-safe:
|
|
523
|
+
|
|
524
|
+
```text
|
|
525
|
+
no external one-shot side effects
|
|
526
|
+
may rerun until assignment is committed
|
|
527
|
+
after assignment commit it is not rerun for that task
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### 8.8 Worker completion
|
|
531
|
+
|
|
532
|
+
Wake-up callbacks are non-authoritative.
|
|
533
|
+
|
|
534
|
+
Reconcile exact reserved worker execution from Persistence and then persist
|
|
535
|
+
TeamExecution worker/task outcome.
|
|
536
|
+
|
|
537
|
+
### 8.9 Aggregator contract
|
|
538
|
+
|
|
539
|
+
`aggregate` is pure/replay-safe result computation.
|
|
540
|
+
|
|
541
|
+
Input is canonical durable assignment results.
|
|
542
|
+
|
|
543
|
+
If the process dies before result/error commit:
|
|
544
|
+
|
|
545
|
+
```text
|
|
546
|
+
run aggregate again
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
No `aggregation=started`, unknown outcome or manual resolution.
|
|
550
|
+
|
|
551
|
+
On normal return/raise:
|
|
552
|
+
|
|
553
|
+
```text
|
|
554
|
+
persist result_ref/error_ref
|
|
555
|
+
terminalize TeamExecution
|
|
556
|
+
TeamRoot -> idle
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### 8.10 Team callbacks
|
|
560
|
+
|
|
561
|
+
Progress and terminal callbacks are Runtime-only observations.
|
|
562
|
+
|
|
563
|
+
No restart-spanning delivery state/index.
|
|
564
|
+
|
|
565
|
+
## 9. Runtime ownership
|
|
566
|
+
|
|
567
|
+
### 9.1 Handoff
|
|
568
|
+
|
|
569
|
+
Same-process HandoffRunner admission prevents competing live controllers for the
|
|
570
|
+
same main Agent/graph.
|
|
571
|
+
|
|
572
|
+
### 9.2 Team
|
|
573
|
+
|
|
574
|
+
If Team is made a stable logical entity, Runtime needs process-local ownership
|
|
575
|
+
similar in intent to Agent ownership:
|
|
576
|
+
|
|
577
|
+
```text
|
|
578
|
+
create/load/get by team_id
|
|
579
|
+
one live owner per Runtime
|
|
580
|
+
definition compatibility
|
|
581
|
+
shutdown draining
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
This registry must not become durable authority; TeamRoot/TeamExecution remain
|
|
585
|
+
Persistence authority.
|
|
586
|
+
|
|
587
|
+
If implementing this registry remains disproportionately complex after the scope
|
|
588
|
+
reductions above, stop and report before adding more abstraction.
|
|
589
|
+
|
|
590
|
+
## 9A. Accepted recovery contract obligations
|
|
591
|
+
|
|
592
|
+
[RECOVERY_CONTRACT_CLARIFICATIONS.md](RECOVERY_CONTRACT_CLARIFICATIONS.md) is a
|
|
593
|
+
normative part of this design, not an optional follow-up plan.
|
|
594
|
+
|
|
595
|
+
| Contract | Implementation obligation |
|
|
596
|
+
|---|---|
|
|
597
|
+
| RC-01 | Public read-only exact execution status/result access and discovery from known owner identity, including retained terminal executions; no implicit continuation/callback/admission |
|
|
598
|
+
| RC-02 | Distinguish authoritative absence, conflict, failed read and unknown commit; preserve operation/Agent/execution IDs and reconcile before further semantic work |
|
|
599
|
+
| RC-03 | Check declared definition compatibility and current required graph/slot wiring; reuse committed facts; Application owns semantic code compatibility |
|
|
600
|
+
| RC-04 | Separate observer detach/shutdown from semantic cancel; map cancellation/admission/settlement and restart discovery to existing Agent contracts |
|
|
601
|
+
| RC-05 | Reuse confirmed outcomes, recover unfinished exact executions, resolve unknown external effects using existing Agent Recovery |
|
|
602
|
+
|
|
603
|
+
API method names are not invented in this documentation update. Before coding,
|
|
604
|
+
map each requirement to baseline public APIs/SPI, implementation and specs. Add
|
|
605
|
+
only genuinely missing capability. Record retention, discovery ambiguity and
|
|
606
|
+
cancel/terminal ordering explicitly in that mapping. A version declaration is
|
|
607
|
+
not permission to resume incompatible code or migrate stored records silently.
|
|
608
|
+
|
|
609
|
+
## 10. Transaction boundaries
|
|
610
|
+
|
|
611
|
+
| Semantic boundary | One durable transaction contains |
|
|
612
|
+
|---|---|
|
|
613
|
+
| Agent normal terminal | existing terminal Agent facts/result/error; **no callback state** |
|
|
614
|
+
| Source Handoff | Source terminal facts + HandoffContext + HandoffState Target reservation |
|
|
615
|
+
| Handoff Target stabilization | Target Agent terminal facts + HandoffState stabilization when applicable |
|
|
616
|
+
| Orchestrator child reservation | parent snapshot with reserved child Agent/execution IDs |
|
|
617
|
+
| Orchestrator child outcome | parent snapshot consumes exact child terminal outcome |
|
|
618
|
+
| Team admission | TeamExecution create_active + TeamRoot active |
|
|
619
|
+
| Team enqueue | canonical task |
|
|
620
|
+
| Team assignment | task -> worker slot + exact reserved worker execution |
|
|
621
|
+
| Team worker outcome | exact worker terminal result applied to TeamExecution |
|
|
622
|
+
| Team aggregate result | final result/error ref after replay-safe aggregate returns/raises |
|
|
623
|
+
| Team terminal | TeamExecution terminal + TeamRoot idle |
|
|
624
|
+
|
|
625
|
+
No callback ACK transaction exists. Every row is subject to RC-02: a lost write
|
|
626
|
+
acknowledgement must be reconciled using existing Persistence mechanisms before
|
|
627
|
+
advancing dependent semantic work. RC-04 cancellation is mapped to existing
|
|
628
|
+
Agent cancellation/terminal barriers; this table does not create a second
|
|
629
|
+
transaction or cancellation engine.
|
|
630
|
+
|
|
631
|
+
## 11. Failure/recovery matrix
|
|
632
|
+
|
|
633
|
+
### 11.1 Agent callback boundary
|
|
634
|
+
|
|
635
|
+
| Failure point | Result |
|
|
636
|
+
|---|---|
|
|
637
|
+
| before terminal commit | normal active recovery |
|
|
638
|
+
| terminal committed, before callback | semantic result remains terminal; callback may be lost |
|
|
639
|
+
| during callback | external effect semantics belong to Application |
|
|
640
|
+
| after callback, before caller Task settlement | lost Task observation allowed; no semantic replay |
|
|
641
|
+
|
|
642
|
+
### 11.2 Handoff
|
|
643
|
+
|
|
644
|
+
| Failure point | Recovery |
|
|
645
|
+
|---|---|
|
|
646
|
+
| before Source transaction | recover Source |
|
|
647
|
+
| after Source transaction, Target absent | start exact reserved Target execution |
|
|
648
|
+
| Target active | recover same execution |
|
|
649
|
+
| Target terminal, HandoffState not stabilized | consume exact terminal and stabilize |
|
|
650
|
+
| graph wiring absent | fail closed |
|
|
651
|
+
|
|
652
|
+
### 11.3 Orchestrator durable path
|
|
653
|
+
|
|
654
|
+
| Failure point | Recovery |
|
|
655
|
+
|---|---|
|
|
656
|
+
| child reserved, Agent absent | create reserved Agent |
|
|
657
|
+
| child Agent exists, execution absent | start reserved execution |
|
|
658
|
+
| child active | recover exact child |
|
|
659
|
+
| child terminal, parent snapshot stale | consume exact terminal and CAS parent snapshot |
|
|
660
|
+
| FSMSession lost | rebuild fresh session from snapshot |
|
|
661
|
+
|
|
662
|
+
Standalone convenience fan-out has no restart guarantee.
|
|
663
|
+
|
|
664
|
+
### 11.4 Team
|
|
665
|
+
|
|
666
|
+
| Failure point | Recovery |
|
|
667
|
+
|---|---|
|
|
668
|
+
| before task enqueue commit | coordinator Agent recovery may replay generation |
|
|
669
|
+
| task enqueue committed | task already exists; do not recreate |
|
|
670
|
+
| before assignment commit | scheduler may rerun |
|
|
671
|
+
| assignment committed, worker absent | start exact reserved worker execution |
|
|
672
|
+
| worker active | recover exact worker |
|
|
673
|
+
| worker terminal, TeamExecution stale | consume exact worker outcome |
|
|
674
|
+
| aggregate running, process dies | rerun replay-safe aggregate |
|
|
675
|
+
| final Team terminal committed, callback missed | semantic result remains terminal; callback may be lost |
|
|
676
|
+
|
|
677
|
+
### 11.5 Common clarification failure matrix
|
|
678
|
+
|
|
679
|
+
| Failure/observation | Required behavior |
|
|
680
|
+
|---|---|
|
|
681
|
+
| Caller lost before receiving committed execution ID | Discover retained active/terminal candidates from known owner; do not infer unique request correlation |
|
|
682
|
+
| Read timeout or decode failure | Return an error; do not treat as absence or successful empty result |
|
|
683
|
+
| Commit acknowledgement lost | Read back same operation/IDs, reconcile facts, no replacement execution |
|
|
684
|
+
| Incompatible/missing current wiring | Fail closed before continuation; read-only outcome access stays independent of execution wiring |
|
|
685
|
+
| Observer disappears or Runtime stops | No implicit semantic cancellation |
|
|
686
|
+
| Explicit parent cancel races with child admission/completion | Reconcile exact child state through existing cancel/terminal barriers; preserve terminal facts and restart discoverability |
|
|
687
|
+
|
|
688
|
+
## 12. Source change map
|
|
689
|
+
|
|
690
|
+
### 12.1 Remove/not implement from previous plan
|
|
691
|
+
|
|
692
|
+
```text
|
|
693
|
+
Agent terminal_delivery helper
|
|
694
|
+
delivery_pending execution index
|
|
695
|
+
TerminalDeliveryRecovery
|
|
696
|
+
callback ACK command/readback
|
|
697
|
+
Agent.load terminal delivery drain
|
|
698
|
+
Team terminal delivery index
|
|
699
|
+
Team aggregation manual-resolution state
|
|
700
|
+
synthetic direct-fan-out AgentExecution mode
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### 12.2 Retain/add
|
|
704
|
+
|
|
705
|
+
```text
|
|
706
|
+
Persistence:
|
|
707
|
+
handoff_states
|
|
708
|
+
teams
|
|
709
|
+
team_executions
|
|
710
|
+
codecs/facades/InMemory/RBS/backend contract
|
|
711
|
+
|
|
712
|
+
Agent:
|
|
713
|
+
reserved execution start
|
|
714
|
+
Handoff domain + HandoffState recovery wiring
|
|
715
|
+
|
|
716
|
+
Orchestrator:
|
|
717
|
+
coordination snapshot for existing parent AgentExecution
|
|
718
|
+
exact child reservation/reconciliation
|
|
719
|
+
recovery reconstruction
|
|
720
|
+
|
|
721
|
+
Team:
|
|
722
|
+
TeamRoot / TeamExecution
|
|
723
|
+
stable coordinator Agent
|
|
724
|
+
durable task/assignment/worker result
|
|
725
|
+
replay-safe scheduler/aggregate contracts
|
|
726
|
+
process-local ownership/recovery adapter
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
## 13. Documentation migration
|
|
730
|
+
|
|
731
|
+
Revise current docs only after implementation.
|
|
732
|
+
|
|
733
|
+
Migration notes must explicitly state:
|
|
734
|
+
|
|
735
|
+
- Handoff namespace clean break;
|
|
736
|
+
- same-Persistence durable Handoff graph;
|
|
737
|
+
- Team stable identity/create/load APIs if retained;
|
|
738
|
+
- durable Team scheduler/aggregate purity/replay contract;
|
|
739
|
+
- standalone Orchestrator fan-out remains Runtime-only;
|
|
740
|
+
- `on_event` is not restart-spanning.
|
|
741
|
+
|
|
742
|
+
## 14. Test requirements
|
|
743
|
+
|
|
744
|
+
### Architecture guards
|
|
745
|
+
|
|
746
|
+
Assert:
|
|
747
|
+
|
|
748
|
+
```text
|
|
749
|
+
no :completing
|
|
750
|
+
no terminal_delivery/delivery_pending persistence surface
|
|
751
|
+
no old MultiAgent Handoff public constants
|
|
752
|
+
no synthetic direct_fan_out durable parent mode
|
|
753
|
+
no persisted Proc/Class/Task/FSMSession
|
|
754
|
+
TeamCoordinator not a Workflow subclass
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### Persistence contract
|
|
758
|
+
|
|
759
|
+
Test:
|
|
760
|
+
|
|
761
|
+
```text
|
|
762
|
+
handoff_states CAS
|
|
763
|
+
teams root revision
|
|
764
|
+
team_executions active admission/CAS
|
|
765
|
+
atomic_all participation
|
|
766
|
+
codec strictness
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
No callback-delivery indexes.
|
|
770
|
+
|
|
771
|
+
### Fault injection
|
|
772
|
+
|
|
773
|
+
Required durable failure cases:
|
|
774
|
+
|
|
775
|
+
```text
|
|
776
|
+
Source Handoff commit -> crash before Target start
|
|
777
|
+
Target exact execution terminal -> crash before Handoff stabilization
|
|
778
|
+
Orchestrator child terminal -> crash before parent snapshot update
|
|
779
|
+
Team assignment commit -> crash before worker start
|
|
780
|
+
Team worker terminal -> crash before TeamExecution update
|
|
781
|
+
Team aggregate invoked -> process loss -> replay-safe rerun
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
Also test intentional non-guarantees:
|
|
785
|
+
|
|
786
|
+
```text
|
|
787
|
+
terminal callback may be lost after process loss
|
|
788
|
+
standalone dispatch_parallel has no restart recovery
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
### Recovery-contract acceptance scenarios
|
|
792
|
+
|
|
793
|
+
Run the RC-01-A through RC-05-A scenarios in
|
|
794
|
+
[the clarification test matrix](RECOVERY_CONTRACT_CLARIFICATIONS.md).
|
|
795
|
+
Record existing coverage and add only missing behavioral/fault cases. Unknown
|
|
796
|
+
commit tests must cover the applicable Handoff, parent snapshot and Team write
|
|
797
|
+
boundaries, rather than only a mocked happy-path read. Cancellation tests include
|
|
798
|
+
admission/terminal races and process loss. No scenario is marked passed by this
|
|
799
|
+
documentation revision.
|
|
800
|
+
|
|
801
|
+
## 15. Definition of Done
|
|
802
|
+
|
|
803
|
+
### Agent
|
|
804
|
+
|
|
805
|
+
- semantic terminal outcome remains durable;
|
|
806
|
+
- no callback-delivery durability subsystem;
|
|
807
|
+
- lost callback never causes semantic replay.
|
|
808
|
+
|
|
809
|
+
### Handoff
|
|
810
|
+
|
|
811
|
+
- Agent namespace clean break;
|
|
812
|
+
- durable active responsibility;
|
|
813
|
+
- atomic Source transfer + exact Target reservation;
|
|
814
|
+
- exact Target recovery;
|
|
815
|
+
- multi-hop/later-turn routing survives process loss;
|
|
816
|
+
- graph absence fails closed.
|
|
817
|
+
|
|
818
|
+
### Orchestrator
|
|
819
|
+
|
|
820
|
+
- coordination inside an Orchestrator AgentExecution has durable child snapshot;
|
|
821
|
+
- child IDs are reserved before semantic work;
|
|
822
|
+
- exact terminal child outcomes are reconciled;
|
|
823
|
+
- fresh runtime FSM is reconstructed;
|
|
824
|
+
- standalone direct fan-out is documented/tested Runtime-only.
|
|
825
|
+
|
|
826
|
+
### Team
|
|
827
|
+
|
|
828
|
+
- stable Team identity/execution;
|
|
829
|
+
- durable tasks/assignments/worker IDs/results;
|
|
830
|
+
- exact worker recovery;
|
|
831
|
+
- scheduler and aggregate are replay-safe contracts;
|
|
832
|
+
- aggregate can be rerun after ambiguous process loss;
|
|
833
|
+
- no terminal callback persistence.
|
|
834
|
+
|
|
835
|
+
### Common
|
|
836
|
+
|
|
837
|
+
- Persistence is the only framework durable backend abstraction;
|
|
838
|
+
- EventLoop remains live single-writer;
|
|
839
|
+
- Runtime objects are never serialized;
|
|
840
|
+
- Application external effects remain Application responsibility;
|
|
841
|
+
- no purpose-unrelated generic identity is introduced;
|
|
842
|
+
- RC-01 through RC-05 are mapped to actual baseline APIs/implementation/specs;
|
|
843
|
+
- result discovery ambiguity and retention limits are documented;
|
|
844
|
+
- cancellation/terminal ordering and restart discovery are verified against existing contracts;
|
|
845
|
+
- full focused/backend/fault/full-suite verification passes on the target checkout.
|
|
846
|
+
|
|
847
|
+
## 16. Stop conditions
|
|
848
|
+
|
|
849
|
+
Implementation must stop and report rather than expand scope if any of the
|
|
850
|
+
following becomes necessary:
|
|
851
|
+
|
|
852
|
+
1. durable Team semantics require serializing Application Proc/Class objects;
|
|
853
|
+
2. durable Orchestrator child recovery requires a global generic class registry;
|
|
854
|
+
3. callback durability is reintroduced merely to recover caller observation;
|
|
855
|
+
4. a convenience API needs a synthetic semantic identity solely to claim
|
|
856
|
+
"everything durable";
|
|
857
|
+
5. Team ownership/recovery requires a second framework execution engine that
|
|
858
|
+
materially duplicates Workflow without clear product value;
|
|
859
|
+
6. a semantic transition would require distributed transactions across independent
|
|
860
|
+
Persistence domains.
|
|
861
|
+
|
|
862
|
+
These are architecture-review triggers, not invitations to add more machinery.
|