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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +2 -2
  3. data/CHANGELOG.md +18 -0
  4. data/CONTRIBUTING.md +2 -2
  5. data/README.md +1 -1
  6. data/docs/architecture/multi-agent-handoff.md +35 -40
  7. data/docs/architecture/persistence.md +19 -8
  8. data/docs/architecture.md +8 -1
  9. data/docs/decisions/016-semantic-multi-agent-handoff.md +3 -1
  10. data/docs/decisions/028-preparing-recovery-replay-contract.md +106 -0
  11. data/docs/decisions/029-semantic-completion-and-application-effect-boundary.md +220 -0
  12. data/docs/decisions/030-agent-handoff-domain-and-durable-responsibility.md +235 -0
  13. data/docs/decisions/031-durable-multi-agent-coordination.md +301 -0
  14. data/docs/decisions/README.md +5 -1
  15. data/docs/design/durable-semantic-coordination/CHANGELOG_V2_REVISION_2.md +33 -0
  16. data/docs/design/durable-semantic-coordination/CONTINUATION_DECISION_REFACTOR.md +191 -0
  17. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_DESIGN_V2.md +862 -0
  18. data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +106 -0
  19. data/docs/design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md +179 -0
  20. data/docs/design/durable-semantic-coordination/RESPONSIBILITY_BOUNDARY_REVIEW.md +302 -0
  21. data/docs/features.md +35 -1
  22. data/docs/migrations/durable-semantic-coordination-v2.md +65 -0
  23. data/docs/persistence-backends.md +42 -3
  24. data/lib/phronomy/agent/agent_execution.rb +2 -2
  25. data/lib/phronomy/agent/agent_invocation.rb +1 -1
  26. data/lib/phronomy/agent/async_event_api.rb +18 -1
  27. data/lib/phronomy/agent/base.rb +28 -0
  28. data/lib/phronomy/agent/context_assembler.rb +1 -1
  29. data/lib/phronomy/agent/exact_execution.rb +153 -0
  30. data/lib/phronomy/agent/execution_cancellation.rb +25 -0
  31. data/lib/phronomy/agent/execution_coordinator.rb +484 -27
  32. data/lib/phronomy/{multi_agent → agent}/handoff.rb +4 -4
  33. data/lib/phronomy/{multi_agent → agent}/handoff_capability_factory.rb +3 -45
  34. data/lib/phronomy/{multi_agent → agent}/handoff_context.rb +26 -1
  35. data/lib/phronomy/{multi_agent/execution_coordinator.rb → agent/handoff_execution_coordinator.rb} +32 -5
  36. data/lib/phronomy/{multi_agent → agent}/handoff_policy.rb +7 -1
  37. data/lib/phronomy/{multi_agent → agent}/handoff_projection.rb +18 -2
  38. data/lib/phronomy/{multi_agent → agent}/handoff_request.rb +2 -2
  39. data/lib/phronomy/agent/handoff_runner.rb +178 -0
  40. data/lib/phronomy/agent/handoff_state.rb +43 -0
  41. data/lib/phronomy/agent/recovery_coordinator/continuation.rb +114 -211
  42. data/lib/phronomy/agent/recovery_coordinator/installation.rb +84 -130
  43. data/lib/phronomy/agent/recovery_coordinator/resolution.rb +76 -200
  44. data/lib/phronomy/agent/recovery_coordinator.rb +11 -5
  45. data/lib/phronomy/agent/recovery_support.rb +15 -23
  46. data/lib/phronomy/agent/ruby_llm_materializer.rb +2 -8
  47. data/lib/phronomy/agent/tool_invocation.rb +4 -2
  48. data/lib/phronomy/engine/runtime/team_ownership_registry.rb +77 -0
  49. data/lib/phronomy/engine/runtime.rb +16 -1
  50. data/lib/phronomy/multi_agent/durable_subagent_coordinator.rb +134 -0
  51. data/lib/phronomy/multi_agent/orchestrator.rb +59 -11
  52. data/lib/phronomy/multi_agent/team_coordinator.rb +473 -125
  53. data/lib/phronomy/multi_agent/team_execution.rb +44 -0
  54. data/lib/phronomy/multi_agent/team_root.rb +41 -0
  55. data/lib/phronomy/persistence/durable_codec.rb +60 -0
  56. data/lib/phronomy/persistence/in_memory.rb +264 -2
  57. data/lib/phronomy/persistence/repository_facades.rb +221 -2
  58. data/lib/phronomy/persistence.rb +95 -1
  59. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +1 -0
  60. data/lib/phronomy/testing/persistence_contract/coordination_repositories.rb +137 -0
  61. data/lib/phronomy/testing/persistence_contract.rb +5 -0
  62. data/lib/phronomy/tools/agent.rb +1 -1
  63. data/lib/phronomy/version.rb +1 -1
  64. data/scripts/api_snapshot.rb +3 -3
  65. data/sig/phronomy/handoff.rbs +41 -0
  66. data/sig/phronomy/multi_agent.rbs +28 -32
  67. data/sig/phronomy/persistence.rbs +64 -3
  68. metadata +44 -12
  69. data/lib/phronomy/multi_agent/coordination_state.rb +0 -18
  70. data/lib/phronomy/multi_agent/coordinator.rb +0 -154
  71. 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.