phronomy 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -0
- data/README.md +7 -2
- data/docs/architecture/agent-tool-child-lifetime.md +141 -0
- data/docs/architecture/dx05-agent-scope.md +4 -2
- data/docs/architecture/r8-unit1.md +68 -68
- data/docs/architecture/r8-unit2.md +34 -34
- data/docs/architecture/structured-output-and-scope.md +73 -13
- data/docs/decisions/029-semantic-completion-and-application-effect-boundary.md +1 -1
- data/docs/decisions/044-agent-default-and-one-shot-composition.md +5 -0
- data/docs/design/durable-semantic-coordination/CHANGELOG_V2_REVISION_2.md +23 -23
- data/docs/design/durable-semantic-coordination/IMPLEMENTATION_REPORT.md +99 -99
- data/docs/design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md +135 -136
- data/docs/getting-started.md +26 -0
- data/docs/migrations/0.31.md +72 -0
- data/lib/phronomy/agent/async_event_api.rb +17 -8
- data/lib/phronomy/agent/base.rb +27 -2
- data/lib/phronomy/agent/composition/run_once.rb +11 -10
- data/lib/phronomy/agent/context_preparation.rb +1 -0
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +1 -1
- data/lib/phronomy/agent/execution/exact_execution.rb +5 -3
- data/lib/phronomy/agent/execution/execution_coordinator.rb +6 -0
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +1 -6
- data/lib/phronomy/agent/execution/initial_preparation.rb +1 -1
- data/lib/phronomy/agent/execution/invocation_actions.rb +17 -15
- data/lib/phronomy/agent/execution_change.rb +4 -0
- data/lib/phronomy/agent/output_contract.rb +47 -5
- data/lib/phronomy/agent/persistence/codec.rb +16 -2
- data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +1 -0
- data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +2 -2
- data/lib/phronomy/agent/runtime_input.rb +7 -0
- data/lib/phronomy/engine/fsm_session.rb +7 -0
- data/lib/phronomy/execution/async_operation.rb +16 -0
- data/lib/phronomy/execution/concurrency/result_finalization.rb +106 -0
- data/lib/phronomy/generation/generator_verifier/agent_operation.rb +3 -3
- data/lib/phronomy/generation/generator_verifier.rb +6 -3
- data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +1 -1
- data/lib/phronomy/llm_adapter/backends/structured_response_capture.rb +3 -1
- data/lib/phronomy/tools/agent.rb +58 -22
- data/lib/phronomy/version.rb +1 -1
- data/sig/phronomy/agent.rbs +7 -5
- data/sig/phronomy/execution/async_operation.rbs +1 -0
- data/sig/phronomy/generation/generator_verifier.rbs +1 -1
- data/sig/phronomy/tools/agent.rbs +14 -0
- metadata +6 -2
|
@@ -8,7 +8,11 @@ authorization and any decision to start another attempt.
|
|
|
8
8
|
## Public behavior
|
|
9
9
|
|
|
10
10
|
`Agent::Base#invoke`, `invoke_async`, `stream`, `stream_async` and
|
|
11
|
-
`start_reserved_async` accept `output_schema: nil
|
|
11
|
+
`start_reserved_async` accept `output_schema: nil` and `schema_delivery: nil`.
|
|
12
|
+
`run_once` forwards both options. With a schema, omitted/nil delivery means
|
|
13
|
+
`:native`; explicit `:native` and `:none` are supported. A non-nil delivery without
|
|
14
|
+
a schema, or any other value, raises ArgumentError before admission. The same
|
|
15
|
+
keywords and final-output semantics apply to sync/async and invoke/stream.
|
|
12
16
|
Without a schema the existing free-text behavior remains. With a schema, successful
|
|
13
17
|
`output` and `result` are deeply frozen JSON objects with String keys; `raw_output`
|
|
14
18
|
preserves the model text. Token events are provisional, not validated objects.
|
|
@@ -45,9 +49,21 @@ values and String/Symbol keys, snapshots recursively, and rejects duplicate norm
|
|
|
45
49
|
keys, Ruby objects and cycles. Generic schema interpretation belongs to C17, not
|
|
46
50
|
Tool::Schema, Agent's caller or Generation.
|
|
47
51
|
|
|
48
|
-
##
|
|
52
|
+
## Schema delivery and completion facts
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
`:native` sends the declared schema to the provider. `:none` omits native schema
|
|
55
|
+
configuration on every turn, including Tool follow-ups, but retains the same
|
|
56
|
+
strict local validation, completion checks, output filters, frozen values and
|
|
57
|
+
OutputError reasons. It does not send JSON mode, rewrite prompts, infer behavior
|
|
58
|
+
from provider/model names, fall back after rejection or regenerate malformed
|
|
59
|
+
output. Applications must already ask for the declared JSON shape in their
|
|
60
|
+
instructions. Tools and their authorization rules remain unchanged.
|
|
61
|
+
|
|
62
|
+
Use `schema_delivery: :none` explicitly where native schema delivery cannot be
|
|
63
|
+
combined with the application's Tools. This does not repair LM Studio PEG errors:
|
|
64
|
+
a provider failure before a usable response remains a provider failure.
|
|
65
|
+
|
|
66
|
+
With `:native`, C09 `LLMAdapter::Request#response_schema` carries the immutable schema; each model
|
|
51
67
|
turn retains it. RubyLLM `with_schema` sends native schema configuration. The
|
|
52
68
|
transport tests cover RubyLLM 2.0.0 OpenAI/Azure Chat Completions and Responses,
|
|
53
69
|
Anthropic, Gemini and Ollama's OpenAI-compatible endpoint. Constraints are compared
|
|
@@ -77,7 +93,7 @@ unknown), refusal and raw_finish_reason metadata. Only normal final completion c
|
|
|
77
93
|
be a structured success. Tool requests are intermediate; they retain existing
|
|
78
94
|
approval, denial, cancellation and recovery behavior. RubyLLM 2.0 loses streamed
|
|
79
95
|
refusal fields in Chunk values; operation-local Protocol subclasses capture these
|
|
80
|
-
raw facts. No SDK global class or shared protocol registry is patched. The SDK's
|
|
96
|
+
raw facts on every stream, independently of native schema delivery. No SDK global class or shared protocol registry is patched. The SDK's
|
|
81
97
|
raw finish information is retained through saved-response recovery.
|
|
82
98
|
|
|
83
99
|
JSON 2.21.2 is the verified minimum for the strict decoding flags and deterministic
|
|
@@ -104,21 +120,28 @@ no arbitrary class name is constantized. Other transport, cancellation, Tool and
|
|
|
104
120
|
internal failures keep their existing behavior. Output failure never triggers an
|
|
105
121
|
automatic regeneration or replay of a completed Tool operation.
|
|
106
122
|
|
|
107
|
-
|
|
108
|
-
at admission. Digest is SHA-256 of UTF-8 JSON generated with recursively sorted keys
|
|
123
|
+
New structured executions store `output_contract` version 2, schema_ref,
|
|
124
|
+
schema_digest and schema_delivery (`"native"` or `"none"`) at admission. Digest is SHA-256 of UTF-8 JSON generated with recursively sorted keys
|
|
109
125
|
(JSON 2.21.2 `sort_keys: true`); the exact same representation is saved in ContentStore.
|
|
110
126
|
This format preserves arbitrary JSON integers and finite floats, including -0.0,
|
|
111
127
|
without applying the narrower Common canonical-domain number rules. Each Context
|
|
112
|
-
Manifest
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
Manifest carries response_schema_ref only for native delivery. The output
|
|
129
|
+
contract always keeps schema_ref, including with `:none`, so local validation
|
|
130
|
+
survives recovery. The digest identifies the schema alone; exact execution identity
|
|
131
|
+
also compares delivery. Resume/approval restore the saved choice, and a reserved
|
|
132
|
+
ID cannot be reused with a different schema or delivery. Generic config/provider
|
|
133
|
+
schema overrides are rejected.
|
|
116
134
|
|
|
117
135
|
Structured success stores JSON result plus raw_output_ref and result_format=json.
|
|
118
136
|
Old records without output_contract remain facts from a free-text execution; no
|
|
119
|
-
schema is added retroactively.
|
|
120
|
-
|
|
121
|
-
|
|
137
|
+
schema is added retroactively. Existing output_contract version 1 is read as
|
|
138
|
+
native delivery and is not rewritten merely by reading. Version-2 contracts use
|
|
139
|
+
AgentExecution envelope 0.3; old/freeform executions retain envelope 0.2. New
|
|
140
|
+
readers accept both explicitly. Older readers reject envelope 0.3, including for
|
|
141
|
+
completed executions, instead of silently losing delivery policy. Deploy compatible
|
|
142
|
+
readers before writing new structured executions; do not downgrade a store that
|
|
143
|
+
contains 0.3 records to older readers. Unknown versions and digest mismatch fail
|
|
144
|
+
closed. Saved LLM responses include finish_reason,
|
|
122
145
|
refusal and metadata; missing finish evidence is unknown, never assumed normal.
|
|
123
146
|
Fresh-runtime and new SQL connection-pool tests verify success, failure and approval
|
|
124
147
|
continuation without replay of confirmed LLM/Tool work. This is a durable-facts
|
|
@@ -126,6 +149,11 @@ claim, not an external side-effect exactly-once guarantee.
|
|
|
126
149
|
|
|
127
150
|
## Generation evaluation
|
|
128
151
|
|
|
152
|
+
`GeneratorVerifier.new` and `.open` accept `schema_delivery: :native` (default) or
|
|
153
|
+
`:none`. One choice applies to both draft and review operations. Their independent
|
|
154
|
+
schemas and C03 evaluation policy remain unchanged; no role-specific flags or
|
|
155
|
+
automatic fallback are introduced.
|
|
156
|
+
|
|
129
157
|
C03 specifies the fixed protocol: draft answer/string, confidence/number in 0..1,
|
|
130
158
|
citations/array; review approved/boolean, score/number in 0..1, feedback/string.
|
|
131
159
|
All outer fields are required and additional properties are forbidden. Default
|
|
@@ -168,6 +196,38 @@ Neither API implicitly cancels work, answers approval, deletes saved data or
|
|
|
168
196
|
closes the application Store. The application decides how unfinished work becomes
|
|
169
197
|
safe before retrying through the cleanup error's scope/pipeline handle.
|
|
170
198
|
|
|
199
|
+
## Single-invocation ownership
|
|
200
|
+
|
|
201
|
+
`Agent.run_once(definition:, input:, context: nil, knowledge: [], on_event: nil,
|
|
202
|
+
**invoke_options, &event_block)` creates a fresh ephemeral Store and owns one
|
|
203
|
+
Agent through `Agent.open_scope`. The definition must be an `Agent::Base`
|
|
204
|
+
subclass. It forwards the input and invocation options, including the output
|
|
205
|
+
schema and delivery selection, and releases the live Agent before returning.
|
|
206
|
+
The application-level Store configuration is not used or changed.
|
|
207
|
+
|
|
208
|
+
Successful cleanup preserves the invocation value or the identical invocation
|
|
209
|
+
exception. A cleanup failure raises `Agent::ScopeCleanupError`: `result` retains
|
|
210
|
+
a successful value, `primary_error` retains an invocation failure, `failures`
|
|
211
|
+
identifies unreleased owners, and `scope.release!` can retry release. It does not
|
|
212
|
+
repeat the invocation, model request or Tool work. Release does not purge records,
|
|
213
|
+
close shared storage or shut down Runtime. No keep-alive option or legacy path
|
|
214
|
+
is provided; use `create`/`load` or an explicit scope for a reusable Agent.
|
|
215
|
+
|
|
216
|
+
The synchronous call cannot run on EventLoop. It rejects that entry before
|
|
217
|
+
creating its Store or Agent. Supplying both `on_event:` and a listener block is
|
|
218
|
+
also rejected before acquisition. The existing listener-error policy is preserved.
|
|
219
|
+
|
|
220
|
+
Approval waits are not completion. The Agent remains owned while the invocation
|
|
221
|
+
waits; the application still decides approval through the existing API. Use
|
|
222
|
+
`approve_async` when another operation is already waiting for the same execution.
|
|
223
|
+
A concurrent synchronous approval or other accepted operation can still own a
|
|
224
|
+
lease when the invocation returns. In that case cleanup reports the busy owner
|
|
225
|
+
through `ScopeCleanupError`; finish the other operation before retrying release.
|
|
226
|
+
Logical cancellation likewise cannot authorize release of physically active work.
|
|
227
|
+
The convenience API neither answers approval nor cancels or waits for unrelated
|
|
228
|
+
work to make cleanup succeed. Applications needing notifications or other work
|
|
229
|
+
after the invocation should express that whole lifetime with `open_scope`.
|
|
230
|
+
|
|
171
231
|
## Dependencies and implementation units
|
|
172
232
|
|
|
173
233
|
- Remove C03 Generation → C17 OutputParser; C03 continues to use public C04 Agent,
|
|
@@ -153,7 +153,7 @@ request deduplication or unambiguous correlation. Existing retention applies.
|
|
|
153
153
|
|
|
154
154
|
Reuse existing APIs where they meet this contract; map missing capabilities only
|
|
155
155
|
after baseline inspection. Do not invent a framework outbox or request registry.
|
|
156
|
-
See [RC-01](RECOVERY_CONTRACT_CLARIFICATIONS.md#1-rc-01
|
|
156
|
+
See [RC-01](../design/durable-semantic-coordination/RECOVERY_CONTRACT_CLARIFICATIONS.md#1-rc-01-accessing-final-results-and-discovering-executions).
|
|
157
157
|
|
|
158
158
|
### 9. Unknown commit outcome and cancellation
|
|
159
159
|
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
**Refines**: [038-responsibility-based-source-layout](038-responsibility-based-source-layout.md)
|
|
6
6
|
and [040-configuration-default-composition](040-configuration-default-composition.md)
|
|
7
7
|
|
|
8
|
+
The original lifetime-preservation decision below is historical. The current
|
|
9
|
+
`run_once` contract owns a scope and releases its Agent; see
|
|
10
|
+
[single-invocation ownership](../architecture/structured-output-and-scope.md#single-invocation-ownership).
|
|
11
|
+
The composition placement and default-factory boundary remain in force.
|
|
12
|
+
|
|
8
13
|
## Problem
|
|
9
14
|
|
|
10
15
|
`Agent::Base` selected the concrete default with `Persistence.in_memory`.
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# V2 revision 2
|
|
1
|
+
# V2 revision 2 - Changes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Updated: 2026-09-06 / Status: Accepted
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Accepted decisions reflected in this revision
|
|
6
6
|
|
|
7
|
-
|
|
|
7
|
+
| Item | Change in this revision |
|
|
8
8
|
|---|---|
|
|
9
|
-
| RC-01
|
|
10
|
-
| RC-02
|
|
11
|
-
| RC-03
|
|
12
|
-
| RC-04
|
|
13
|
-
| RC-05
|
|
9
|
+
| RC-01 Result access | Add contracts for reading status/results by exact execution ID and discovering candidates from the owner if execution is interrupted before the caller receives the ID |
|
|
10
|
+
| RC-02 Unknown persistence outcomes | Distinguish confirmed absence, read failure, CAS conflict, and unknown commit outcome; reconcile using the same reserved identity |
|
|
11
|
+
| RC-03 Wiring compatibility | Specify minimum checks for definition id/version, slot, graph, and Persistence boundary, and give precedence to committed facts |
|
|
12
|
+
| RC-04 Cancellation | Distinguish ending observation/shutdown from semantic cancellation; specify handling by child state, races, and rediscovery after restart |
|
|
13
|
+
| RC-05 Guarantee wording | Use consistent wording: reuse committed outcomes, recover with the same identity, and resolve uncertain external outcomes through existing Recovery |
|
|
14
14
|
|
|
15
|
-
ADR-029/030/031
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
The corresponding normative statements have been incorporated into ADR-029/030/031, the implementation design, the responsibility boundary review, and the README.
|
|
16
|
+
Detailed contracts and validation conditions are collected in RECOVERY_CONTRACT_CLARIFICATIONS.md and referenced across the documents.
|
|
17
|
+
The pre-approval Proposed status has been changed to Accepted. This does not request renewed approval of the new functionality.
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Correction of implementation status
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
Earlier implementation counts and successful static checks in the handoff document remain reports from the previous session.
|
|
22
|
+
They are not evidence that implementation was revalidated in this continuation. Only the design documents and handoff document are currently available;
|
|
23
|
+
the old overlay/apply.py/APPLY.sh/VERIFY.sh have not been recovered. The resumption procedure has also been updated to begin by recovering the actual files.
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Checks performed for this revision
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- RC-01
|
|
30
|
-
- ZIP
|
|
27
|
+
- Check consistency of approval status, baseline, and cross-references in the affected documents.
|
|
28
|
+
- Correct obsolete statements that implementation was stopped pending approval and guarantee wording that could imply exactly-once external effects.
|
|
29
|
+
- Check the mapping of RC-01 through RC-05 to ADRs, implementation design, and validation conditions.
|
|
30
|
+
- Verify the ZIP layout, SHA256SUMS for all documents, and external SHA256 values for the ZIP and handoff document.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
API
|
|
32
|
+
No code changes or RSpec runs were performed in the target repository.
|
|
33
|
+
Unverified API or exception names were not invented; mapping the requirements to the baseline was made mandatory before implementation.
|
|
@@ -6,107 +6,107 @@
|
|
|
6
6
|
> [ADR-034](../../decisions/034-handoff-runner-coordination-ownership.md).
|
|
7
7
|
> Handoff and HandoffPolicy remain in Agent at this stage.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
Created: 2026-09-07. Design approved: 2026-09-06.
|
|
10
|
+
Baseline: `5472116cd99a63ec27875024c955ea82be612d6b`.
|
|
11
|
+
This is a new implementation of the approved ADR-029/030/031 and RC-01 through RC-05.
|
|
12
|
+
It does not use the old Complete Durability overlay, existing work ZIPs, or synthetic fan-out executions.
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Implementation scope
|
|
15
15
|
|
|
16
|
-
|
|
|
16
|
+
| Area | Implemented behavior |
|
|
17
17
|
|---|---|
|
|
18
|
-
| Persistence | root
|
|
19
|
-
| Handoff | Agent-domain API
|
|
20
|
-
| Orchestrator |
|
|
21
|
-
| Team | TeamRoot/TeamExecution
|
|
22
|
-
| Team
|
|
23
|
-
| Aggregate |
|
|
24
|
-
| Runtime |
|
|
25
|
-
| Recovery | framework-owned
|
|
26
|
-
|
|
|
27
|
-
|
|
28
|
-
Handoff graph
|
|
29
|
-
|
|
30
|
-
Runtime
|
|
31
|
-
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
|
|
|
18
|
+
| Persistence | Eight repositories in both root and transaction views; the three new records use current format `0.1`. Backend handles opaque DurableRecords and explicit identity/revision/index metadata |
|
|
19
|
+
| Handoff | Moved to the Agent-domain API. Source terminal state, Context, exact Target reservation, and responsibility transfer are persisted in one transaction. Target terminal state and routing stabilization also share one transaction |
|
|
20
|
+
| Orchestrator | Stores child ID/input/knowledge/config/outcome for static subagent Tools in the existing parent AgentExecution. Direct `dispatch_parallel`/`fan_out` calls do not create synthetic parents |
|
|
21
|
+
| Team | Persists TeamRoot/TeamExecution, tasks, worker slots, and exact assignments/outcomes using CAS. Coordinators/workers use the existing Agent engine. Scheduling retains the existing sequential approach |
|
|
22
|
+
| Internal Team operations | Applies persisted authorized Tool batches in Provider order. Retains the result of each `tool_invocation_id` and automatically reconciles `enqueue_task`/`finalize` |
|
|
23
|
+
| Aggregate | Pure/replay-safe computation. Commits canonical JSON results or errors as terminal outcomes. Recalculation is possible after a crash before persistence, but not for a persisted terminal outcome |
|
|
24
|
+
| Runtime | Adds process-local Team ownership, admission, and draining. Does not add a new Team FSM/Workflow engine |
|
|
25
|
+
| Recovery | Resumes framework-owned operations from exact facts. In batches mixed with external Tools, only external facts are resolved through the existing Recovery API |
|
|
26
|
+
| Termination and deletion | Retains cancellation/reconciliation information for exact children. `purge!` on an idle main Agent also deletes the Handoff anchor; deleting an anchor for an incomplete turn is rejected |
|
|
27
|
+
|
|
28
|
+
A Handoff graph uses the same Persistence **instance**. The original main Agent ID is the routing anchor.
|
|
29
|
+
Persisted Context is not reprojected using a new policy, and persisted worker assignments are not reselected using the current scheduler.
|
|
30
|
+
Runtime Classes/Procs, listeners, Tasks, and CancellationTokens are not persisted.
|
|
31
|
+
|
|
32
|
+
## Public entry points
|
|
33
|
+
|
|
34
|
+
| Purpose | API / return value |
|
|
35
35
|
|---|---|
|
|
36
|
-
| Agent
|
|
37
|
-
| Handoff
|
|
38
|
-
| Agent
|
|
39
|
-
| Team
|
|
40
|
-
| Team
|
|
41
|
-
| Handoff
|
|
42
|
-
|
|
|
43
|
-
| Team
|
|
44
|
-
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Agent
|
|
50
|
-
|
|
51
|
-
`class`/`message
|
|
52
|
-
|
|
53
|
-
Handoff
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
`Team.load
|
|
59
|
-
Agent
|
|
60
|
-
Team
|
|
61
|
-
`Team.stream
|
|
62
|
-
|
|
63
|
-
## RC
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`spec/phronomy/multi_agent/durable_coordination_spec.rb
|
|
67
|
-
|
|
68
|
-
|
|
|
36
|
+
| Agent result access | `store.execution_result(execution_id)`; a frozen Hash containing owner, status, phase, result/error, and reference IDs |
|
|
37
|
+
| Handoff result access | `store.handoff_result(source_execution_id)`; follows the exact Target of that turn. No graph/Agent hydration is required |
|
|
38
|
+
| Agent execution discovery | `store.list_executions(agent_id, after: nil, limit: 100)`; immutable execution records, both active and terminal |
|
|
39
|
+
| Team result access | `store.team_execution_result(run_id)` or `team.result(run_id)` |
|
|
40
|
+
| Team execution discovery | `store.list_team_executions(team_id, after: nil, limit: 100)` or `team.executions(...)` |
|
|
41
|
+
| Handoff execution/recovery | `Agent::HandoffRunner.new(main_agent:, handoffs:).invoke(input, config: {})`; uses the persisted reservation and input if an incomplete turn exists |
|
|
42
|
+
| Static child recovery | `Orchestrator#resume(execution_id, config: {})` |
|
|
43
|
+
| Team creation/recovery | `team_definition id:, version:`, `create(team_id:, persistence:)`, `load(team_id, persistence:, on_event:)`, `resume(run_id)` |
|
|
44
|
+
| Explicit cancellation | `team.cancel(run_id)` / `handoff_runner.cancel(execution_id)`; existing Agent operations, including Orchestrator, use `config[:cancellation_token]` |
|
|
45
|
+
|
|
46
|
+
Lists are ordered lexicographically by semantic ID; `after` is an exclusive ID cursor, and `limit` is a positive integer.
|
|
47
|
+
This does not imply chronological ordering or unique correspondence to a request. Applications match candidates against their own correlation information.
|
|
48
|
+
|
|
49
|
+
Agent result status uses existing Symbols; Team result status uses canonical Strings.
|
|
50
|
+
The default Team aggregate result is also canonical JSON: Hash keys are Strings, and errors are data such as
|
|
51
|
+
`class`/`message`, not exception objects. Top-level assignment keys and task keys passed to aggregate are Symbols.
|
|
52
|
+
|
|
53
|
+
An unstarted Handoff Target reservation is identified by `status: :active, phase: :target_pending, reserved: true`.
|
|
54
|
+
Explicit cancellation of an unstarted Target preserves its reserved ID; a later turn never substitutes for the result of an earlier turn.
|
|
55
|
+
Absence produces `Persistence::NotFoundError`; read/decode failures produce their actual errors.
|
|
56
|
+
No facility to restore deleted results or retain them indefinitely has been added.
|
|
57
|
+
|
|
58
|
+
`Team.load` hydrates Team facts only. Child execution/recovery starts through `resume`.
|
|
59
|
+
Agent `load` retains its existing Recovery contract. Use the Persistence access APIs above when only results are needed.
|
|
60
|
+
Team's `on_event` is passed to hidden Agents to receive required Recovery/approval events.
|
|
61
|
+
`Team.stream` provides Runtime notifications of committed assignments; it adds no notification-delivery guarantee.
|
|
62
|
+
|
|
63
|
+
## RC mapping
|
|
64
|
+
|
|
65
|
+
Paths are relative to the repository root. The shared additional fault specs are in
|
|
66
|
+
`spec/phronomy/multi_agent/durable_coordination_spec.rb`.
|
|
67
|
+
|
|
68
|
+
| Requirement | Main implementation | Validation evidence |
|
|
69
69
|
|---|---|---|
|
|
70
|
-
| RC-01-A/B | `Persistence#execution_result` / `list_executions
|
|
71
|
-
| RC-01-C | `Persistence#handoff_result
|
|
72
|
-
| RC-02-A |
|
|
73
|
-
| RC-02-B/C |
|
|
74
|
-
| RC-03-A | Team definition
|
|
75
|
-
| RC-03-B |
|
|
76
|
-
| RC-04-A |
|
|
77
|
-
| RC-04-B/C/D | Team
|
|
78
|
-
| RC-04-E | Source terminal link
|
|
79
|
-
| RC-05 |
|
|
80
|
-
|
|
81
|
-
`lib/phronomy/testing/persistence_contract/coordination_repositories.rb
|
|
82
|
-
|
|
83
|
-
raw SPI/API
|
|
84
|
-
logical-operation tracing
|
|
85
|
-
|
|
86
|
-
##
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
InMemory
|
|
99
|
-
-
|
|
100
|
-
durable
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
callback outbox/ACK
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
##
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
70
|
+
| RC-01-A/B | `Persistence#execution_result` / `list_executions`, and corresponding Team APIs | Reads active/terminal candidates, pagination, and results in a reconstructed environment without loading the owner; does not invoke Providers or add ownership registrations |
|
|
71
|
+
| RC-01-C | `Persistence#handoff_result`, read-only materialization | Reservation access without graph/owner, read failures, and NotFound for purged results. Callback policy is also covered by the existing `stream_callback_error_policy_spec.rb` |
|
|
72
|
+
| RC-02-A | Existing F1 readback during Agent preparation, `reconcile_terminal_error`, Team `admit`/`update` | Lost acknowledgements immediately after each Team revision commit and Source transfer; reuse of committed worker/child outcomes |
|
|
73
|
+
| RC-02-B/C | Exact reservation reconciliation, atomic admission/CAS, bounded readback | Distinguishes read failure from absence. No dispatch after a failed readback following Team admission. Backend contracts check stale CAS, duplicate active records, and rollback across eight repositories |
|
|
74
|
+
| RC-03-A | Team definition snapshots, static child slot definitions, Handoff graph/Target matching | Fails closed on worker-version mismatch or missing Target/graph. Existing Handoff integration specs reject a different Persistence instance |
|
|
75
|
+
| RC-03-B | Immutable Context/input/knowledge/assignment/outcome | Uses persisted HandoffContext even when the current policy changes. Preserves worker results, static child results, and knowledge metadata |
|
|
76
|
+
| RC-04-A | Existing Task waiting/Runtime shutdown contracts | `task_spec.rb`, `agent/acs16_task_quiescence_spec.rb`, and Runtime/admission specs. Runtime reconstruction tests introduce no implicit cancellation |
|
|
77
|
+
| RC-04-B/C/D | Team cancellation flags, exact Handoff cancellation, Agent child-admission conditions, existing terminal barriers | Preserves reserved worker/Target IDs without starting them. A parent with an active child awaiting external facts remains active, persists cancellation information, and retains it after restart. Checked together with existing admission/physical-quiescence specs |
|
|
78
|
+
| RC-04-E | Source terminal link and Target cancellation; responsibility remains with Target | Cancellation after transfer, restart, and a later turn do not return responsibility to Source; historical reserved IDs and cancellation results are preserved |
|
|
79
|
+
| RC-05 | Separation of callbacks/external effects from semantic records | Mixed external/framework Tool batches resolve only external facts and do not rerun completed children. Application is not asked to determine facts about internal `finalize` |
|
|
80
|
+
|
|
81
|
+
The new shared examples in `lib/phronomy/testing/persistence_contract/coordination_repositories.rb`
|
|
82
|
+
run through `phronomy/testing/persistence_contract`, which is also exposed to external backends.
|
|
83
|
+
Existing guards for raw SPI/API snapshots/RBS, removal of old Handoff constants, the EventLoop single writer/causal barrier,
|
|
84
|
+
and logical-operation tracing are preserved.
|
|
85
|
+
|
|
86
|
+
## Validation scope and limitations
|
|
87
|
+
|
|
88
|
+
The measured environment is Ruby 3.3.6. Gem versions are recorded in the distribution ZIP's `verification/gems.txt`.
|
|
89
|
+
See the accompanying verification records for commands, results, and logs measured against the distributed files.
|
|
90
|
+
|
|
91
|
+
- Ordinary RSpec runs exclude integration tags requiring connections to external LLMs.
|
|
92
|
+
- Selected Handoff/Orchestrator/Team integration tests run with WebMock.
|
|
93
|
+
- Added F4 tests model recovery by copying committed DurableRecords and using a new Backend and Runtime.
|
|
94
|
+
They do not demonstrate forced termination of a real OS process or fsync to physical storage.
|
|
95
|
+
- Separate suites using live LLMs, Redis, PostgreSQL, OpenTelemetry, and similar dependencies are outside this measurement.
|
|
96
|
+
There are 61 pending cases: 59 with optional dependencies/services unconfigured and two existing obsolete cases.
|
|
97
|
+
- F4 durability and exclusion across multiple processes for external backends depend on the backend and deployment contracts.
|
|
98
|
+
InMemory itself does not guarantee persistence after process termination.
|
|
99
|
+
- Semantic cancellation does not roll back external effects. Token objects are Runtime-only.
|
|
100
|
+
Committed durable cancellation flags/facts are retained, and uncertain external operations are reconciled through existing Recovery.
|
|
101
|
+
Waiting for facts/approval is not converted into failure that forgets a child; control returns through `ExecutionRehydrationRequiredError`.
|
|
102
|
+
|
|
103
|
+
The framework reuses committed outcomes and recovers incomplete executions with the same semantic identity.
|
|
104
|
+
It adds no callback outbox/ACK, global generic class registry, Proc/Class persistence, distributed transaction,
|
|
105
|
+
or second execution engine dedicated to Team.
|
|
106
|
+
|
|
107
|
+
## Package
|
|
108
|
+
|
|
109
|
+
The package includes complete files and a deletion manifest. Application checks the baseline and pre/post-application hashes.
|
|
110
|
+
New Class locations follow Zeitwerk naming conventions; the old overlay's decorator ignore is unnecessary.
|
|
111
|
+
The old `MultiAgent::Handoff*`, `Runner`, `Coordinator`, and `CoordinationState` implementations are removed.
|
|
112
|
+
See `README_APPLY_JA.md` at the distribution root for application, dependencies, and VERIFY procedures.
|