phronomy 0.22.0 → 0.23.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/.mutant.yml +3 -4
- data/CHANGELOG.md +200 -10
- data/CONTRIBUTING.md +81 -9
- data/README.md +15 -6
- data/VERIFY.sh +587 -0
- data/benchmark/bench_agent_invoke.rb +2 -2
- data/benchmark/bench_context_assembler.rb +39 -68
- data/benchmark/bench_regression.rb +2 -2
- data/docs/architecture/agent-context.md +174 -0
- data/docs/architecture/before-llm-input.md +78 -0
- data/docs/architecture/context-management.md +232 -0
- data/docs/architecture/knowledge-and-rag.md +130 -0
- data/docs/architecture/multi-agent-handoff.md +152 -0
- data/docs/architecture/persistence.md +175 -0
- data/docs/architecture/removed/agent-context.md +72 -0
- data/docs/architecture/security-boundaries.md +173 -0
- data/docs/architecture/tracing.md +194 -0
- data/docs/architecture.md +82 -0
- data/docs/archive/design/archived/04_api_design.md +507 -0
- data/docs/archive/design/archived/09_guardrails.md +186 -0
- data/docs/archive/design/archived/17_rails_integration.md +175 -0
- data/docs/archive/design/historical/00_design_philosophy.md +122 -0
- data/docs/archive/design/historical/01_rubyllm_evaluation.md +178 -0
- data/docs/archive/design/historical/06_design_decisions.md +143 -0
- data/docs/changelog/0.14-and-earlier.md +1 -1
- data/docs/decisions/001-rubyllm-as-provider-layer.md +6 -1
- data/docs/decisions/002-workflow-context-immutability.md +26 -1
- data/docs/decisions/006-no-built-in-guardrails.md +2 -1
- data/docs/decisions/012-canonical-execution-log-and-context-policy.md +120 -38
- data/docs/decisions/014-unified-persistence-durable-state.md +9 -2
- data/docs/decisions/016-semantic-multi-agent-handoff.md +112 -0
- data/docs/decisions/017-design-authority-and-adr-governance.md +200 -0
- data/docs/decisions/018-durability-guarantees-and-failure-model.md +488 -0
- data/docs/decisions/019-filter-contract-and-security-boundaries.md +229 -0
- data/docs/decisions/020-canonical-workflow-instance-identity.md +177 -0
- data/docs/decisions/021-generic-agent-invocation-identity-removal.md +119 -0
- data/docs/decisions/022-agent-execution-parent-identity-and-runtime-routing-boundary.md +193 -0
- data/docs/decisions/023-fsm-session-incarnation-identity-and-routing.md +139 -0
- data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +188 -0
- data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +249 -0
- data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +257 -0
- data/docs/decisions/027-llm-adapter-provider-boundary.md +93 -0
- data/docs/decisions/README.md +172 -0
- data/docs/features.md +31 -11
- data/docs/getting-started.md +77 -45
- data/docs/migrations/0.19.md +14 -7
- data/docs/migrations/0.22.md +390 -0
- data/docs/persistence-backends.md +88 -38
- data/docs/runtime-and-concurrency.md +227 -33
- data/examples/README.md +13 -0
- data/lib/phronomy/agent/agent_execution.rb +19 -15
- data/lib/phronomy/agent/agent_invocation.rb +288 -93
- data/lib/phronomy/agent/agent_invocation_session_builder.rb +236 -202
- data/lib/phronomy/agent/agent_root.rb +3 -3
- data/lib/phronomy/agent/approval_evaluation_request.rb +37 -19
- data/lib/phronomy/agent/async_event_api.rb +145 -72
- data/lib/phronomy/agent/base.rb +388 -181
- data/lib/phronomy/agent/concerns/before_llm_input.rb +1 -1
- data/lib/phronomy/agent/context_assembler.rb +437 -178
- data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
- data/lib/phronomy/agent/context_plan.rb +18 -13
- data/lib/phronomy/agent/context_plan_validator.rb +246 -88
- data/lib/phronomy/agent/context_policies/default.rb +123 -34
- data/lib/phronomy/agent/context_policy.rb +109 -3
- data/lib/phronomy/agent/context_policy_input.rb +244 -0
- data/lib/phronomy/agent/context_policy_input_builder.rb +241 -0
- data/lib/phronomy/agent/execution_coordinator.rb +1975 -587
- data/lib/phronomy/agent/journal_record.rb +17 -4
- data/lib/phronomy/agent/llm_input_build_context.rb +1 -1
- data/lib/phronomy/agent/llm_input_manifest.rb +277 -2
- data/lib/phronomy/agent/llm_operation_result.rb +12 -7
- data/lib/phronomy/agent/phase_machine_builder.rb +19 -7
- data/lib/phronomy/agent/provider_call_outcome.rb +23 -7
- data/lib/phronomy/agent/recovery_coordinator/continuation.rb +271 -0
- data/lib/phronomy/agent/recovery_coordinator/installation.rb +427 -0
- data/lib/phronomy/agent/recovery_coordinator/resolution.rb +635 -0
- data/lib/phronomy/agent/recovery_coordinator.rb +211 -0
- data/lib/phronomy/agent/recovery_support.rb +512 -0
- data/lib/phronomy/agent/ruby_llm_materializer.rb +22 -13
- data/lib/phronomy/agent/selection/candidate.rb +53 -0
- data/lib/phronomy/agent/selection/constraint.rb +49 -0
- data/lib/phronomy/agent/shared_state.rb +38 -1
- data/lib/phronomy/agent/tool_approval_request.rb +33 -5
- data/lib/phronomy/agent/tool_definition_set.rb +49 -3
- data/lib/phronomy/agent/tool_invocation.rb +336 -102
- data/lib/phronomy/agent/tool_invocation_session_builder.rb +49 -45
- data/lib/phronomy/agent.rb +20 -2
- data/lib/phronomy/agent_already_exists_error.rb +5 -0
- data/lib/phronomy/agent_purged_error.rb +5 -0
- data/lib/phronomy/engine/concurrency/offload_pool.rb +17 -3
- data/lib/phronomy/engine/concurrency/physical_completion_task.rb +135 -0
- data/lib/phronomy/engine/event_loop.rb +622 -63
- data/lib/phronomy/engine/fsm_session.rb +194 -21
- data/lib/phronomy/engine/runtime/agent_ownership_registry.rb +352 -0
- data/lib/phronomy/engine/runtime.rb +77 -20
- data/lib/phronomy/generator_verifier.rb +12 -14
- data/lib/phronomy/invocation_context.rb +9 -29
- data/lib/phronomy/multi_agent/admission_registry.rb +51 -0
- data/lib/phronomy/multi_agent/coordination_state.rb +18 -0
- data/lib/phronomy/multi_agent/coordinator.rb +154 -0
- data/lib/phronomy/multi_agent/execution_coordinator.rb +116 -0
- data/lib/phronomy/multi_agent/fan_out_invocation.rb +24 -33
- data/lib/phronomy/multi_agent/fan_out_session_builder.rb +12 -19
- data/lib/phronomy/multi_agent/handoff.rb +24 -45
- data/lib/phronomy/multi_agent/handoff_capability_factory.rb +87 -0
- data/lib/phronomy/multi_agent/handoff_context.rb +95 -0
- data/lib/phronomy/multi_agent/handoff_policy.rb +137 -0
- data/lib/phronomy/multi_agent/handoff_projection.rb +191 -0
- data/lib/phronomy/multi_agent/handoff_request.rb +45 -0
- data/lib/phronomy/multi_agent/orchestrator.rb +12 -15
- data/lib/phronomy/multi_agent/runner.rb +98 -0
- data/lib/phronomy/persistence/durable_codec.rb +646 -0
- data/lib/phronomy/persistence/durable_record.rb +117 -0
- data/lib/phronomy/persistence/in_memory.rb +210 -134
- data/lib/phronomy/persistence/migration/initial_format_migration.rb +226 -0
- data/lib/phronomy/persistence/repository_facades.rb +316 -0
- data/lib/phronomy/persistence.rb +81 -41
- data/lib/phronomy/recovery.rb +186 -0
- data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
- data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +1 -1
- data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +19 -19
- data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +3 -3
- data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
- data/lib/phronomy/tracing/automatic.rb +176 -0
- data/lib/phronomy/tracing/base.rb +11 -2
- data/lib/phronomy/tracing/langfuse_tracer.rb +20 -12
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/workflow.rb +3 -6
- data/lib/phronomy/workflow_context.rb +14 -5
- data/lib/phronomy/workflow_recovery.rb +123 -0
- data/lib/phronomy/workflow_runner.rb +468 -256
- data/lib/phronomy.rb +6 -0
- data/scripts/api_snapshot.rb +12 -0
- data/sig/phronomy/agent.rbs +209 -7
- data/sig/phronomy/multi_agent.rbs +39 -0
- data/sig/phronomy/persistence.rbs +62 -4
- data/sig/phronomy/runtime.rbs +1 -4
- data/sig/phronomy/workflow.rbs +2 -2
- data/sig/phronomy.rbs +10 -0
- metadata +65 -17
- data/examples/workflows/agent_event_mapping.rb +0 -101
- data/examples/workflows/generic_task_event_mapping.rb +0 -66
- data/lib/phronomy/agent/activation_registry.rb +0 -28
- data/lib/phronomy/agent/agent_execution_activation.rb +0 -172
- data/lib/phronomy/agent/context_candidate.rb +0 -47
- data/lib/phronomy/agent/context_parts/budget/token_budget_packer.rb +0 -53
- data/lib/phronomy/agent/context_parts/requirements/required_context_resolver.rb +0 -56
- data/lib/phronomy/agent/context_parts/selectors/recent_first_selector.rb +0 -30
- data/lib/phronomy/agent/context_parts/unit_builders/dependency_aware_unit_builder.rb +0 -118
- data/lib/phronomy/agent/context_policy_descriptor.rb +0 -49
- data/lib/phronomy/agent/context_policy_registry.rb +0 -46
- data/lib/phronomy/agent/context_request.rb +0 -35
- data/lib/phronomy/agent/context_selection_unit.rb +0 -38
- data/lib/phronomy/agent/derived_content_spec.rb +0 -34
- data/lib/phronomy/agent/runner.rb +0 -97
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# ADR-018: Durability Guarantees and Failure Model Vocabulary
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted.
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-08-23
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Phronomy already has concrete durability, transaction, concurrency,
|
|
14
|
+
cancellation and fault-handling behavior, but terms such as "durable",
|
|
15
|
+
"recoverable", "safe", "conflict protection" and "exactly once" can describe
|
|
16
|
+
materially different guarantees.
|
|
17
|
+
|
|
18
|
+
That ambiguity is unsafe for later recovery and distributed-ownership work.
|
|
19
|
+
A durable record being readable after restart does not imply that a lost
|
|
20
|
+
execution can resume. Transaction atomicity does not imply that a caller can
|
|
21
|
+
always determine whether a commit occurred. Optimistic conflict detection
|
|
22
|
+
does not imply distributed exclusion. Neither durability nor exclusion
|
|
23
|
+
implies exactly-once execution of external side effects.
|
|
24
|
+
|
|
25
|
+
This ADR establishes the repository-wide guarantee vocabulary and failure
|
|
26
|
+
taxonomy used by architecture review, fault-injection review and downstream
|
|
27
|
+
Architecture Change Sets.
|
|
28
|
+
|
|
29
|
+
It is a normative **target architecture contract**. It does not claim that
|
|
30
|
+
every target guarantee below is already implemented. Known implementation
|
|
31
|
+
gaps remain explicit downstream reconciliation work.
|
|
32
|
+
|
|
33
|
+
## Decision
|
|
34
|
+
|
|
35
|
+
### 1. Guarantee statements name the subject, property and provider
|
|
36
|
+
|
|
37
|
+
Do not use a bare statement such as:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
recoverable = yes
|
|
41
|
+
safe = yes
|
|
42
|
+
durable = yes
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
A guarantee statement must make clear:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
guarantee subject + guarantee property
|
|
49
|
+
provided / enforced by
|
|
50
|
+
guarantee provider / contract
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For example:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
Agent logical state:
|
|
57
|
+
logical-state rehydration = YES
|
|
58
|
+
provided by supported Agent load/hydration + Persistence
|
|
59
|
+
|
|
60
|
+
In-flight external Tool execution:
|
|
61
|
+
execution resumption = CONDITIONAL
|
|
62
|
+
provided only when its recovery/integration contract supports safe
|
|
63
|
+
reconciliation or replay
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Canonical guarantee vocabulary
|
|
67
|
+
|
|
68
|
+
The following ten terms are distinct guarantees.
|
|
69
|
+
|
|
70
|
+
#### G1 — durable state persistence
|
|
71
|
+
|
|
72
|
+
**Subject:** semantic state/records explicitly defined as durable Phronomy
|
|
73
|
+
state, such as AgentRoot, JournalRecord, AgentExecution, durable Workflow
|
|
74
|
+
checkpoints and content-addressed Content.
|
|
75
|
+
|
|
76
|
+
**Guarantee:** after a known-successful Persistence commit, the state is held
|
|
77
|
+
in durable storage independently of process-local Runtime object lifetime.
|
|
78
|
+
|
|
79
|
+
**Provider:** Phronomy Persistence contract plus a conforming backend.
|
|
80
|
+
|
|
81
|
+
Process-local objects such as FSMSession, Activation, AgentInvocation, Task
|
|
82
|
+
and EventLoop queue entries are not covered by this guarantee.
|
|
83
|
+
|
|
84
|
+
#### G2 — durable-state restart readability
|
|
85
|
+
|
|
86
|
+
**Subject:** state/records already durably committed.
|
|
87
|
+
|
|
88
|
+
**Guarantee:** after Phronomy Runtime/process restart, the state can be read
|
|
89
|
+
through the supported Persistence API.
|
|
90
|
+
|
|
91
|
+
**Provider:** Persistence contract plus backend.
|
|
92
|
+
|
|
93
|
+
Readability does not imply logical-state rehydration or execution resumption.
|
|
94
|
+
|
|
95
|
+
#### G3 — logical-state rehydration
|
|
96
|
+
|
|
97
|
+
**Subject:** state of a logical entity with durable identity.
|
|
98
|
+
|
|
99
|
+
**Guarantee:** supported Phronomy APIs can construct usable live/domain state
|
|
100
|
+
representing the same logical entity from confirmed durable state, without
|
|
101
|
+
requiring the old process-local Ruby/Runtime objects.
|
|
102
|
+
|
|
103
|
+
**Provider:** Phronomy load/hydration semantics plus Persistence.
|
|
104
|
+
|
|
105
|
+
Rehydration does not restore the pre-crash object graph and does not itself
|
|
106
|
+
imply execution resumption.
|
|
107
|
+
|
|
108
|
+
#### G4 — execution resumption
|
|
109
|
+
|
|
110
|
+
**Subject:** an unfinished logical execution/continuation.
|
|
111
|
+
|
|
112
|
+
**Guarantee:** supported recovery/resume semantics can continue the same
|
|
113
|
+
logical execution from durable recovery state without blindly re-executing
|
|
114
|
+
semantic work already known to have completed.
|
|
115
|
+
|
|
116
|
+
**Provider:** Phronomy Runtime/recovery/resume semantics together with the
|
|
117
|
+
relevant operation-specific recovery contracts.
|
|
118
|
+
|
|
119
|
+
A durable AgentExecution record is necessary recovery evidence but is not,
|
|
120
|
+
by itself, an execution-resumption guarantee.
|
|
121
|
+
|
|
122
|
+
#### G5 — durable-transition atomicity
|
|
123
|
+
|
|
124
|
+
**Subject:** one semantic durable transition whose durable mutations are
|
|
125
|
+
defined as one transaction boundary.
|
|
126
|
+
|
|
127
|
+
**Guarantee:** durable mutations in that transition commit all-or-nothing.
|
|
128
|
+
|
|
129
|
+
**Provider:** Persistence transaction contract plus backend.
|
|
130
|
+
|
|
131
|
+
Atomicity does not guarantee that the caller can always know a commit's
|
|
132
|
+
outcome after a transport/database failure.
|
|
133
|
+
|
|
134
|
+
#### G6 — same-process competing-execution exclusion
|
|
135
|
+
|
|
136
|
+
**Subject:** competing semantic executions for one logical entity that must
|
|
137
|
+
not be admitted concurrently.
|
|
138
|
+
|
|
139
|
+
**Guarantee:** one Phronomy Runtime/process does not concurrently admit the
|
|
140
|
+
prohibited competing executions.
|
|
141
|
+
|
|
142
|
+
**Provider:** Phronomy Runtime/admission semantics and, where applicable,
|
|
143
|
+
process-local/backend admission mechanics.
|
|
144
|
+
|
|
145
|
+
This does not exclude immutable reads or observation.
|
|
146
|
+
|
|
147
|
+
#### G7 — cross-process competing-execution exclusion
|
|
148
|
+
|
|
149
|
+
**Subject:** the same competing executions across multiple processes,
|
|
150
|
+
containers, replicas or Runtime instances.
|
|
151
|
+
|
|
152
|
+
**Guarantee:** prohibited competing executions are not simultaneously
|
|
153
|
+
admitted across those environments.
|
|
154
|
+
|
|
155
|
+
**Provider:** Phronomy plus stable routing/partitioning or a cross-process
|
|
156
|
+
coordination mechanism that establishes exclusive ownership.
|
|
157
|
+
|
|
158
|
+
A process-local registry, Mutex or optimistic CAS alone is not this guarantee.
|
|
159
|
+
|
|
160
|
+
#### G8 — stale durable-transition conflict detection
|
|
161
|
+
|
|
162
|
+
**Subject:** a durable write/transition based on a stale revision, Journal
|
|
163
|
+
position, watermark or equivalent durable base.
|
|
164
|
+
|
|
165
|
+
**Guarantee:** the stale transition is detected and rejected instead of
|
|
166
|
+
silently overwriting newer durable state.
|
|
167
|
+
|
|
168
|
+
**Provider:** Persistence optimistic revision/CAS/watermark contract plus the
|
|
169
|
+
Phronomy layer that uses it correctly.
|
|
170
|
+
|
|
171
|
+
Conflict detection is not competing-execution exclusion and cannot roll back
|
|
172
|
+
an already-performed external side effect.
|
|
173
|
+
|
|
174
|
+
#### G9 — duplicate external-side-effect prevention
|
|
175
|
+
|
|
176
|
+
**Subject:** one semantic side effect outside Phronomy's durable transaction
|
|
177
|
+
domain, such as an external API update, payment, email, external database
|
|
178
|
+
mutation or application callback effect.
|
|
179
|
+
|
|
180
|
+
**Guarantee:** under the defined failure/retry/recovery conditions, the same
|
|
181
|
+
semantic side effect does not become effective more than once.
|
|
182
|
+
|
|
183
|
+
**Provider:** Phronomy semantic identity/retry/recovery behavior together
|
|
184
|
+
with whatever external idempotency/deduplication protocol is required.
|
|
185
|
+
|
|
186
|
+
A semantic ID existing in Phronomy does not, by itself, provide this guarantee.
|
|
187
|
+
|
|
188
|
+
#### G10 — exactly-once external-side-effect execution
|
|
189
|
+
|
|
190
|
+
**Subject:** one semantic external side effect.
|
|
191
|
+
|
|
192
|
+
**Guarantee:** within the stated failure model the side effect becomes
|
|
193
|
+
effective exactly once: neither zero times nor more than once.
|
|
194
|
+
|
|
195
|
+
**Provider:** never assumed to be Phronomy alone. It requires sufficient
|
|
196
|
+
external-system protocol, idempotency and/or transaction coordination.
|
|
197
|
+
|
|
198
|
+
Duplicate prevention is weaker than exactly-once: a system can avoid
|
|
199
|
+
duplicates while still permitting zero executions after failure.
|
|
200
|
+
|
|
201
|
+
### 3. Guarantee terms are not an implication hierarchy
|
|
202
|
+
|
|
203
|
+
These guarantees do not imply each other unless another architecture contract
|
|
204
|
+
says so.
|
|
205
|
+
|
|
206
|
+
In particular:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
durable state persistence
|
|
210
|
+
!= durable-state restart readability
|
|
211
|
+
!= logical-state rehydration
|
|
212
|
+
!= execution resumption
|
|
213
|
+
|
|
214
|
+
durable-transition atomicity
|
|
215
|
+
!= commit outcome certainty
|
|
216
|
+
|
|
217
|
+
same-process competing-execution exclusion
|
|
218
|
+
!= cross-process competing-execution exclusion
|
|
219
|
+
|
|
220
|
+
stale durable-transition conflict detection
|
|
221
|
+
!= competing-execution exclusion
|
|
222
|
+
|
|
223
|
+
cross-process competing-execution exclusion
|
|
224
|
+
!= duplicate external-side-effect prevention
|
|
225
|
+
!= exactly-once external-side-effect execution
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`durable state`, `durable transition`, and `durable barrier` also remain
|
|
229
|
+
separate architecture concepts. A durable barrier is continuation ordering
|
|
230
|
+
around a confirmed durable outcome; it is not EventLoop-wide blocking and
|
|
231
|
+
does not create X0 external-effect atomicity.
|
|
232
|
+
|
|
233
|
+
### 4. Canonical failure taxonomy
|
|
234
|
+
|
|
235
|
+
`F0` through `F4` are identifiers, not a severity scale, execution-stage
|
|
236
|
+
ordering, containment hierarchy or recovery-difficulty ranking. One scenario
|
|
237
|
+
may match more than one failure class.
|
|
238
|
+
|
|
239
|
+
#### F0 — Operation Failure
|
|
240
|
+
|
|
241
|
+
**Analysis subject:** one semantic/runtime operation.
|
|
242
|
+
|
|
243
|
+
The operation starts but does not reach its contract-defined normal
|
|
244
|
+
completion. Exceptions, explicit errors, rejection, cancellation and timeout
|
|
245
|
+
are possible concrete mechanisms.
|
|
246
|
+
|
|
247
|
+
F0 and F1 describe different dimensions and may apply to the same scenario.
|
|
248
|
+
F0 means the Phronomy operation did not reach contract-defined normal
|
|
249
|
+
completion. F1 may simultaneously apply when the underlying durable or
|
|
250
|
+
external outcome cannot be determined. Do not infer outcome certainty merely
|
|
251
|
+
from an F0 result.
|
|
252
|
+
|
|
253
|
+
#### F1 — Outcome Uncertainty
|
|
254
|
+
|
|
255
|
+
**Analysis subject:** Phronomy's knowledge about an operation, durable
|
|
256
|
+
transition or external effect outcome.
|
|
257
|
+
|
|
258
|
+
Phronomy cannot determine whether the operation succeeded, whether a durable
|
|
259
|
+
transition committed, or whether an external effect occurred.
|
|
260
|
+
|
|
261
|
+
Observing an error/connection loss does not prove that the remote operation
|
|
262
|
+
did not occur or that a commit did not happen.
|
|
263
|
+
|
|
264
|
+
F1 therefore requires reconciliation/recovery treatment rather than blind
|
|
265
|
+
inference from the failure response.
|
|
266
|
+
|
|
267
|
+
#### F2 — Concurrency Conflict
|
|
268
|
+
|
|
269
|
+
**Analysis subject:** multiple actors/operations competing over the same
|
|
270
|
+
logical entity, state or execution lifecycle.
|
|
271
|
+
|
|
272
|
+
The class identifies the conflict. It does not decide whether architecture
|
|
273
|
+
prevents admission, detects stale state after admission, or permits the
|
|
274
|
+
concurrency.
|
|
275
|
+
|
|
276
|
+
#### F3 — Asynchronous Lifecycle Mismatch
|
|
277
|
+
|
|
278
|
+
**Analysis subject:** an asynchronous completion and the lifecycle/owner that
|
|
279
|
+
could accept it.
|
|
280
|
+
|
|
281
|
+
The receiver's execution context, FSMSession, operation generation or
|
|
282
|
+
authority has ended, cancelled, resumed, changed or been replaced before the
|
|
283
|
+
completion arrives. Late completion, duplicate completion and an event
|
|
284
|
+
targeting an old session are examples.
|
|
285
|
+
|
|
286
|
+
#### F4 — Execution-Environment Loss
|
|
287
|
+
|
|
288
|
+
**Analysis subject:** process-local Runtime state supporting a logical
|
|
289
|
+
execution.
|
|
290
|
+
|
|
291
|
+
Runtime/process loss makes live objects such as Activation,
|
|
292
|
+
AgentInvocation, FSMSession, Task, EventLoop queue and Runtime-local admission
|
|
293
|
+
unavailable.
|
|
294
|
+
|
|
295
|
+
F4 does not imply that confirmed durable state was lost. It is the primary
|
|
296
|
+
reason recovery must not depend on old live Runtime objects.
|
|
297
|
+
|
|
298
|
+
#### X0 — External Effect Boundary
|
|
299
|
+
|
|
300
|
+
`X0` is **not a failure class**. It is a boundary label.
|
|
301
|
+
|
|
302
|
+
X0 identifies semantic effects outside Phronomy's durable transaction domain,
|
|
303
|
+
including Tool/provider/application/remote-system effects. Unless an explicit
|
|
304
|
+
protocol provides stronger coordination, such effects are not atomic with a
|
|
305
|
+
Phronomy Persistence transaction.
|
|
306
|
+
|
|
307
|
+
F0-F4 can occur on either side of X0. Combining X0 with F1, retry, recovery or
|
|
308
|
+
competing execution is where duplicate-prevention and exactly-once questions
|
|
309
|
+
become significant.
|
|
310
|
+
|
|
311
|
+
### 5. Failure-model assumptions
|
|
312
|
+
|
|
313
|
+
Core guarantee analysis assumes:
|
|
314
|
+
|
|
315
|
+
- Persistence backends honor the Phronomy Persistence contract.
|
|
316
|
+
- Tool, LLMAdapter and application extension code honor their published
|
|
317
|
+
contracts.
|
|
318
|
+
- process-local Runtime state may be lost under F4.
|
|
319
|
+
- confirmed durable backend state survives according to the backend's own
|
|
320
|
+
durability guarantee.
|
|
321
|
+
- OS, database, network and external services may fail.
|
|
322
|
+
- X0 external side effects and Phronomy Persistence commits are not one atomic
|
|
323
|
+
transaction unless a specific protocol says otherwise.
|
|
324
|
+
|
|
325
|
+
Storage-media destruction, backup/restore policy, multi-region disaster
|
|
326
|
+
recovery and malicious/contract-violating extension code are outside the
|
|
327
|
+
general Phronomy core guarantee.
|
|
328
|
+
|
|
329
|
+
### 6. Final guarantee matrix
|
|
330
|
+
|
|
331
|
+
The matrix uses:
|
|
332
|
+
|
|
333
|
+
```text
|
|
334
|
+
YES baseline target guarantee
|
|
335
|
+
CONDITIONAL guarantee only when the stated additional condition holds
|
|
336
|
+
NO not a baseline guarantee
|
|
337
|
+
N/A not applicable to that subject
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
A `CONDITIONAL` row is incomplete without its condition.
|
|
341
|
+
|
|
342
|
+
#### Durable state
|
|
343
|
+
|
|
344
|
+
| Subject | Durable persistence | Restart readability | Logical rehydration |
|
|
345
|
+
|---|---|---|---|
|
|
346
|
+
| Durable Agent state | **YES** | **YES** | **YES** |
|
|
347
|
+
| AgentExecution / Journal | **YES** | **YES** | **YES** — as logical continuation state/evidence |
|
|
348
|
+
| Durable Workflow checkpoint | **YES** | **YES** | **YES** |
|
|
349
|
+
| Ephemeral Workflow state | **NO** | **NO** | **NO** |
|
|
350
|
+
| Runtime objects (FSMSession, Activation, Task, etc.) | **NO** | **NO** | **N/A** — object itself is not rehydrated |
|
|
351
|
+
|
|
352
|
+
Logical rehydration reconstructs current logical/domain state from confirmed
|
|
353
|
+
durable state; it does not restore the old Ruby object graph.
|
|
354
|
+
|
|
355
|
+
#### Execution resumption
|
|
356
|
+
|
|
357
|
+
| Subject | Guarantee |
|
|
358
|
+
|---|---|
|
|
359
|
+
| Restart-safe HITL durable continuation | **YES** |
|
|
360
|
+
| Durable Workflow continuation | **CONDITIONAL** — dependency consistency and ownership requirements must hold |
|
|
361
|
+
| Process loss with no unresolved external semantic operation | **YES** |
|
|
362
|
+
| In-flight LLM Provider Call | **CONDITIONAL** — operation recovery classification/integration contract |
|
|
363
|
+
| In-flight Tool Execution | **CONDITIONAL** — operation recovery classification/integration contract |
|
|
364
|
+
| Outcome uncertain and not safely resolvable by Phronomy/integration contract | **CONDITIONAL** — Application resolution is required |
|
|
365
|
+
| Terminal Execution | **N/A** |
|
|
366
|
+
|
|
367
|
+
`logical-state rehydration = YES` never means unconditional automatic resume.
|
|
368
|
+
Ownership, durable dependency consistency and pending-operation recovery
|
|
369
|
+
classification govern safe continuation.
|
|
370
|
+
|
|
371
|
+
#### Durable transition and concurrency
|
|
372
|
+
|
|
373
|
+
| Guarantee | Agent | Workflow |
|
|
374
|
+
|---|---|---|
|
|
375
|
+
| Durable-transition atomicity | **YES** | **YES** — for a defined durable transition |
|
|
376
|
+
| Same-process competing-execution exclusion | **YES** | **YES** |
|
|
377
|
+
| Cross-process competing-execution exclusion | **CONDITIONAL** | **CONDITIONAL** |
|
|
378
|
+
| Stale durable-transition conflict detection | **YES** | **YES** |
|
|
379
|
+
|
|
380
|
+
Cross-process exclusion requires stable application routing/partitioning or a
|
|
381
|
+
cross-process coordinator that provides exclusive ownership. Persistence CAS
|
|
382
|
+
or revision checking alone is not enough.
|
|
383
|
+
|
|
384
|
+
#### Cancellation and Task invariants
|
|
385
|
+
|
|
386
|
+
| Subject | Guarantee |
|
|
387
|
+
|---|---|
|
|
388
|
+
| Prevent late result from updating live state after cancellation/authority loss | **YES** |
|
|
389
|
+
| Cancellation request physically terminates the worker/external operation | **NO** |
|
|
390
|
+
| Runtime supervises cancelling/cancelled work until quiescence or operation-specific safe detach | **YES** |
|
|
391
|
+
| Waiter-local timeout cancels the Execution | **NO** |
|
|
392
|
+
| Semantic deadline invalidates result authority | **YES** |
|
|
393
|
+
| Caller Task settlement coincides with the authoritative completion boundary | **YES** |
|
|
394
|
+
| Runtime Task object itself is recovered after restart | **NO** |
|
|
395
|
+
|
|
396
|
+
#### External side effects
|
|
397
|
+
|
|
398
|
+
| Guarantee | Baseline |
|
|
399
|
+
|---|---|
|
|
400
|
+
| Retry eligibility is based on operation-specific contract and outcome certainty | **YES** |
|
|
401
|
+
| Blind automatic retry when safety is not established | **NO** |
|
|
402
|
+
| Reconciliation capability is usable when the integration provides it | **YES** |
|
|
403
|
+
| Arbitrary external-effect duplicate prevention | **CONDITIONAL** — external idempotency/deduplication or equivalent contract is required |
|
|
404
|
+
| Arbitrary external-effect exactly-once execution | **NO** |
|
|
405
|
+
|
|
406
|
+
### 7. Review and test usage
|
|
407
|
+
|
|
408
|
+
Architecture-sensitive failure/recovery/concurrency changes must state:
|
|
409
|
+
|
|
410
|
+
1. the guarantee subject;
|
|
411
|
+
2. the guarantee property from G1-G10;
|
|
412
|
+
3. the provider/condition that makes the guarantee true;
|
|
413
|
+
4. the applicable failure class(es) F0-F4;
|
|
414
|
+
5. whether X0 is crossed;
|
|
415
|
+
6. whether the claimed result is YES, CONDITIONAL or NO in the target matrix.
|
|
416
|
+
|
|
417
|
+
Fault-injection tests should identify the failure class/boundary they exercise.
|
|
418
|
+
A test that observes F0 must not be presented as F1 reconciliation coverage.
|
|
419
|
+
A graceful Runtime shutdown test is not automatically F4 recovery coverage.
|
|
420
|
+
A Tool failure test crossing X0 does not prove duplicate prevention or
|
|
421
|
+
exactly-once behavior.
|
|
422
|
+
|
|
423
|
+
The taxonomy is architecture/test vocabulary. This ADR does **not** add a
|
|
424
|
+
public `FailureClass` enum, public guarantee-level enum or one-error-class-per-
|
|
425
|
+
failure-category hierarchy. Observable public errors are designed only where
|
|
426
|
+
a concrete API contract requires them.
|
|
427
|
+
|
|
428
|
+
### 8. Relationship to current implementation and downstream ACS work
|
|
429
|
+
|
|
430
|
+
This ADR intentionally separates vocabulary from implementation mechanics.
|
|
431
|
+
|
|
432
|
+
Known downstream responsibility includes:
|
|
433
|
+
|
|
434
|
+
- ACS-14: cross-process ownership/fencing and G7 conditions.
|
|
435
|
+
- ACS-15: F1/F4 durable recovery, reconciliation and execution resumption.
|
|
436
|
+
- ACS-16: cancellation supervision and caller-facing Task settlement.
|
|
437
|
+
- ACS-17: X0 semantic retry, outcome certainty, causal durable barriers and
|
|
438
|
+
duplicate/side-effect guarantees.
|
|
439
|
+
- ACS-02: final explanatory architecture guarantee matrix/document placement.
|
|
440
|
+
|
|
441
|
+
Existing ADRs remain authoritative for their current scopes:
|
|
442
|
+
|
|
443
|
+
- ADR-010: EventLoop/FSMSession/Task/Offload concurrency boundary.
|
|
444
|
+
- `011-delegate-transport-policy-to-adapters`: transport retry ownership.
|
|
445
|
+
- ADR-012: canonical Journal/Manifest authority.
|
|
446
|
+
- ADR-014: unified durable Persistence intent until coherent successor
|
|
447
|
+
decisions replace stale portions.
|
|
448
|
+
- ADR-017: repository Design Authority/governance.
|
|
449
|
+
|
|
450
|
+
This ADR does not silently declare known implementation gaps resolved. Later
|
|
451
|
+
ACS changes use this vocabulary to state exactly which target guarantee they
|
|
452
|
+
implement.
|
|
453
|
+
|
|
454
|
+
## Consequences
|
|
455
|
+
|
|
456
|
+
### Positive
|
|
457
|
+
|
|
458
|
+
- "durable", "recoverable" and "safe" can no longer hide different guarantees.
|
|
459
|
+
- F0 known failure and F1 outcome uncertainty are reviewably distinct.
|
|
460
|
+
- cross-process exclusion cannot be mistaken for optimistic conflict
|
|
461
|
+
detection.
|
|
462
|
+
- external duplicate prevention cannot be inferred from a semantic ID alone.
|
|
463
|
+
- exactly-once external effects remain explicitly outside the unconditional
|
|
464
|
+
Phronomy baseline.
|
|
465
|
+
- recovery/fencing/cancellation/retry work shares one acceptance vocabulary.
|
|
466
|
+
|
|
467
|
+
### Trade-offs
|
|
468
|
+
|
|
469
|
+
- architecture-sensitive PRs must state guarantees and failure conditions more
|
|
470
|
+
precisely.
|
|
471
|
+
- the normative matrix can temporarily describe target behavior that current
|
|
472
|
+
source has not yet reconciled; those gaps must remain explicit.
|
|
473
|
+
- deployment-specific details are not encoded in this ADR. The ADR fixes the
|
|
474
|
+
semantic conditions; deployment documentation explains how a particular
|
|
475
|
+
deployment satisfies them.
|
|
476
|
+
|
|
477
|
+
## Non-goals
|
|
478
|
+
|
|
479
|
+
This ADR does not:
|
|
480
|
+
|
|
481
|
+
- introduce public failure/guarantee enums;
|
|
482
|
+
- add new Runtime/Persistence error classes merely to mirror F0-F4;
|
|
483
|
+
- implement cross-process coordination;
|
|
484
|
+
- implement restart recovery/reconciliation;
|
|
485
|
+
- redesign cancellation/Task settlement;
|
|
486
|
+
- introduce semantic external-operation retry;
|
|
487
|
+
- claim arbitrary external exactly-once execution;
|
|
488
|
+
- perform the final ACS-02 architecture-document migration.
|