phronomy 0.29.0 → 0.30.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 +96 -1
- data/README.md +17 -6
- data/docs/architecture/agent-configuration-and-tool-binding.md +8 -0
- data/docs/architecture/agent-iteration-budget.md +81 -0
- data/docs/architecture/dx05-agent-scope.md +9 -2
- data/docs/architecture/error-api-review.md +4 -4
- data/docs/architecture/generator-verifier-lifecycle-result.md +126 -0
- data/docs/architecture/generator-verifier-ownership.md +18 -109
- data/docs/architecture/llm-continuation-metadata.md +88 -0
- data/docs/architecture/lm-studio-output-failures.md +111 -0
- data/docs/architecture/r8-unit15.md +3 -0
- data/docs/architecture/r8-unit7.md +2 -1
- data/docs/architecture/structured-output-and-scope.md +183 -0
- data/docs/architecture/tracing.md +22 -4
- data/docs/architecture/transport-error-boundaries.md +103 -0
- data/docs/architecture/trust-acceptance-followup.md +87 -0
- data/docs/features.md +10 -1
- data/docs/migrations/r8-unit15.md +3 -0
- data/gemfiles/http_minimum.gemfile +6 -1
- data/lib/phronomy/agent/admission.rb +1 -1
- data/lib/phronomy/agent/async_event_api.rb +16 -7
- data/lib/phronomy/agent/base.rb +8 -1
- data/lib/phronomy/agent/context_importer.rb +4 -0
- data/lib/phronomy/agent/execution/agent_invocation.rb +6 -2
- data/lib/phronomy/agent/execution/dispatch_preparation.rb +6 -1
- data/lib/phronomy/agent/execution/exact_execution.rb +9 -0
- data/lib/phronomy/agent/execution/execution_cancellation.rb +1 -1
- data/lib/phronomy/agent/execution/execution_coordinator.rb +63 -5
- data/lib/phronomy/agent/execution/execution_outcome_committer.rb +24 -4
- data/lib/phronomy/agent/execution/execution_registry.rb +5 -1
- data/lib/phronomy/agent/execution/initial_preparation.rb +10 -1
- data/lib/phronomy/agent/execution/invocation_actions.rb +1 -1
- data/lib/phronomy/agent/execution/invocation_transitions.rb +4 -4
- data/lib/phronomy/agent/execution/iteration_budget.rb +35 -0
- data/lib/phronomy/agent/execution/runtime_record_encoder.rb +3 -0
- data/lib/phronomy/agent/execution_observation.rb +5 -5
- data/lib/phronomy/agent/lifecycle/scope.rb +33 -23
- data/lib/phronomy/agent/lifecycle/scope_cleanup_error.rb +4 -2
- data/lib/phronomy/agent/output_contract.rb +64 -0
- data/lib/phronomy/agent/output_error.rb +53 -0
- data/lib/phronomy/agent/recovery/recovery_coordinator/continuation.rb +3 -3
- data/lib/phronomy/agent/recovery/recovery_coordinator/installation.rb +1 -0
- data/lib/phronomy/agent/recovery/recovery_coordinator.rb +1 -1
- data/lib/phronomy/agent/recovery/recovery_support.rb +5 -1
- data/lib/phronomy/agent/runtime_binding/engine_session_builder.rb +2 -1
- data/lib/phronomy/agent/runtime_input.rb +15 -4
- data/lib/phronomy/agent/saved_context_reader.rb +2 -1
- data/lib/phronomy/agent/store.rb +10 -2
- data/lib/phronomy/common/values/immutable.rb +33 -0
- data/lib/phronomy/context/assembly.rb +7 -4
- data/lib/phronomy/embeddings/backends/ruby_llm_embeddings.rb +3 -1
- data/lib/phronomy/engine/fsm_session.rb +16 -1
- data/lib/phronomy/generation/generator_verifier/agent_operation.rb +28 -5
- data/lib/phronomy/generation/generator_verifier/agent_result_receiver.rb +14 -27
- data/lib/phronomy/generation/generator_verifier/approval.rb +30 -0
- data/lib/phronomy/generation/generator_verifier/cleanup_error.rb +15 -0
- data/lib/phronomy/generation/generator_verifier/invocation.rb +147 -0
- data/lib/phronomy/generation/generator_verifier/pipeline_state.rb +16 -0
- data/lib/phronomy/generation/generator_verifier/protocol.rb +55 -0
- data/lib/phronomy/generation/generator_verifier/result.rb +121 -0
- data/lib/phronomy/generation/generator_verifier/unaccepted_result_error.rb +14 -0
- data/lib/phronomy/generation/generator_verifier/workflow_builder.rb +13 -11
- data/lib/phronomy/generation/generator_verifier.rb +170 -85
- data/lib/phronomy/llm_adapter/backends/lm_studio.rb +139 -0
- data/lib/phronomy/llm_adapter/backends/ruby_llm.rb +134 -12
- data/lib/phronomy/llm_adapter/backends/structured_response_capture.rb +41 -0
- data/lib/phronomy/llm_adapter/message.rb +4 -0
- data/lib/phronomy/llm_adapter/request.rb +17 -2
- data/lib/phronomy/llm_adapter/response.rb +11 -4
- data/lib/phronomy/llm_adapter/structured_output_unsupported_error.rb +14 -0
- data/lib/phronomy/llm_adapter/transport_error.rb +4 -0
- data/lib/phronomy/multi_agent/shared_state.rb +1 -0
- data/lib/phronomy/output_parser/json_schema_parser.rb +113 -0
- data/lib/phronomy/output_parser/parse_error.rb +10 -1
- data/lib/phronomy/runtime_composition/agent_defaults.rb +4 -0
- data/lib/phronomy/tracing/automatic.rb +14 -8
- data/lib/phronomy/tracing/base.rb +2 -1
- data/lib/phronomy/tracing/langfuse_tracer.rb +3 -3
- data/lib/phronomy/tracing/observation.rb +2 -1
- data/lib/phronomy/tracing/open_telemetry_tracer.rb +3 -3
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy.rb +1 -2
- data/scripts/api_snapshot.rb +3 -0
- data/scripts/migrate_generator_verifier_result.rb +18 -0
- data/sig/phronomy/agent/execution_contract.rbs +4 -3
- data/sig/phronomy/agent.rbs +20 -7
- data/sig/phronomy/extensions.rbs +8 -3
- data/sig/phronomy/generation/generator_verifier.rbs +70 -0
- data/sig/phronomy/llm_adapter/backends/lm_studio.rbs +8 -0
- data/sig/phronomy/llm_adapter/backends/ruby_llm.rbs +1 -0
- data/sig/phronomy/llm_adapter/values.rbs +8 -2
- data/sig/phronomy/tracing/observation.rbs +1 -1
- data/sig/phronomy.rbs +2 -0
- metadata +59 -8
- data/lib/phronomy/generation/generator_verifier/default_parser.rb +0 -27
- data/lib/phronomy/generation/low_confidence_error.rb +0 -14
- data/lib/phronomy/runtime_composition/generation_defaults.rb +0 -6
- data/sig/phronomy/generation/low_confidence_error.rbs +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46b13a1255f5821e321de0e3817f9fc2335ae2eba81dc7142a01295ffffcdd05
|
|
4
|
+
data.tar.gz: c268bfd441361880ce4c6c6a84f03e7e0530b5e1ca8736e87bfba78756a69c89
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f53504e27f5cefedb2370ed495387c17cf98ae850b847497090b17fe1971545a565bfe4533368f47646c5953352aebc4f29801afdb3a2691a54927f60ec1df4
|
|
7
|
+
data.tar.gz: 4f9dace274b6a09ad4096569cd8a459dc74df63263c8d4fdc1455d6628e70c93464490a971c638a24aea844d09eb85f9f4ceafa64e9c9e39f5345daa6b83fffb
|
data/CHANGELOG.md
CHANGED
|
@@ -12,7 +12,102 @@ Release history for 0.14.0 and earlier is archived in
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
## [0.30.0] - 2026-10-24
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Agent `output_schema:` and `OutputParser::JsonSchemaParser` provide strict,
|
|
20
|
+
immutable JSON results. Refused, incomplete and invalid output raises
|
|
21
|
+
`Agent::OutputError`; native schema delivery is preserved through Tool rounds,
|
|
22
|
+
approval and recovery without output repair or replaying confirmed Tool work.
|
|
23
|
+
- Explicit `LLMAdapter::LMStudio` selection identifies the known generated-format
|
|
24
|
+
rejection as `llm.provider_output_parse_failed`, retaining the actual HTTP
|
|
25
|
+
status and original SDK cause. Opt-in retry resends the same eligible,
|
|
26
|
+
non-streaming gpt-oss-20b request at most once, without replaying Agent,
|
|
27
|
+
Workflow or Tool work. Ordinary SDK retries are disabled in this backend's
|
|
28
|
+
private snapshot; the default backend and global SDK settings are unchanged.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- GeneratorVerifier owns immutable evaluation Results, explicit approval routing
|
|
33
|
+
and Agent lifetime. Use `accepted?`, `termination_reason` and
|
|
34
|
+
`raise_if_unaccepted`; `output_failed` distinguishes invalid output from a
|
|
35
|
+
completed evaluation that reaches `iteration_limit`. Acceptance reports the
|
|
36
|
+
configured conditions, not the truth of generated content.
|
|
37
|
+
- Agent scopes and GeneratorVerifier scopes await a directly returned TaskResult
|
|
38
|
+
before releasing their owned Agents. Cleanup preserves the primary failure,
|
|
39
|
+
successful value and handles needed to retry release.
|
|
40
|
+
- Tracing usage is a plain token-count Hash. Custom tracer/exporter callers must
|
|
41
|
+
project LLM-domain TokenUsage values before crossing the tracing boundary.
|
|
42
|
+
- Require Faraday 2.14.4 and faraday-net_http 3.4.4 as the tested HTTP support
|
|
43
|
+
floors. Concrete LLM/Embeddings adapters translate recognized network failures
|
|
44
|
+
into their public TransportError types while preserving causes and callback
|
|
45
|
+
exceptions; cancellation and unknown internal failures are not broadly mapped.
|
|
46
|
+
Strict JSON decoding requires JSON >= 2.21.2 and < 3.
|
|
47
|
+
|
|
48
|
+
### Removed
|
|
49
|
+
|
|
50
|
+
- GeneratorVerifier parser fallback/repair hooks, `trusted`/`trusted?`,
|
|
51
|
+
`raise_if_untrusted` and `LowConfidenceError`. Migrate saved Result data with
|
|
52
|
+
`scripts/migrate_generator_verifier_result.rb`; no compatibility aliases are
|
|
53
|
+
provided. See the [Result and lifetime contract](docs/architecture/generator-verifier-lifecycle-result.md).
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- Preserve each SharedState member's explicitly configured model when creating
|
|
58
|
+
its internal instrumented Agent. Keep ordinary Agent inheritance and the
|
|
59
|
+
global fallback for members without an explicit model unchanged.
|
|
60
|
+
- Preserve canonical assistant-message metadata through Agent Tool rounds,
|
|
61
|
+
imports, persistence and recovery. The RubyLLM backend retains supported
|
|
62
|
+
thinking text/signatures and raw reasoning, including final streaming
|
|
63
|
+
responses, and delegates wire rendering to the existing SDK. Incompatible
|
|
64
|
+
continuation scope/version is rejected before inference; legacy messages
|
|
65
|
+
without this metadata remain usable. No database migration is required. See
|
|
66
|
+
[continuation compatibility](docs/architecture/llm-continuation-metadata.md).
|
|
67
|
+
- Enforce `Agent.max_iterations = N` as at most N logical LLM calls per
|
|
68
|
+
execution, including the first and final response. Remove the premature FSM
|
|
69
|
+
cutoff that stopped the ninth single-Tool round before call ten. Tool count,
|
|
70
|
+
approval/resume, streaming chunks and SDK HTTP retries do not consume extra
|
|
71
|
+
logical calls; this limit does not bound physical HTTP attempts or Tool count.
|
|
72
|
+
Preserve the admitted limit and consumed-call records across approval,
|
|
73
|
+
recovery and a fresh Runtime/database pool. Legacy executions without the
|
|
74
|
+
saved limit use the current class setting. A final response on call N succeeds;
|
|
75
|
+
Tools requested on call N retain their results, and call N+1 raises the existing
|
|
76
|
+
`RecursionLimitError`. Zero permits no call; invalid limits fail before inference.
|
|
77
|
+
Generic Engine transition protection remains in place. This correction can
|
|
78
|
+
allow work previously stopped too early and stop runs previously able to reset
|
|
79
|
+
their budget on approval. Deploy at a quiescent Runtime boundary; see
|
|
80
|
+
[iteration budget migration](docs/architecture/agent-iteration-budget.md).
|
|
81
|
+
|
|
82
|
+
### Verification and migration
|
|
83
|
+
|
|
84
|
+
- Real LM Studio acceptance identified HTTP 400 PEG failures, performed one
|
|
85
|
+
identical-request retry, and returned the final error at the adapter's own
|
|
86
|
+
limit after the second failure. A separate application invocation succeeded
|
|
87
|
+
initially with HTTP 200: two application invocations, three generation POSTs.
|
|
88
|
+
This is not recovery by retry within one invocation. Recovery by retry,
|
|
89
|
+
recovery rate, the PEG root cause and recurrence resolution remain unverified.
|
|
90
|
+
- Review the [structured-output migration](docs/architecture/structured-output-and-scope.md),
|
|
91
|
+
[continuation compatibility](docs/architecture/llm-continuation-metadata.md),
|
|
92
|
+
[iteration budget migration](docs/architecture/agent-iteration-budget.md) and
|
|
93
|
+
[LM Studio retry policy](docs/architecture/lm-studio-output-failures.md) before
|
|
94
|
+
upgrading persistent or in-flight applications.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## [0.29.0] - 2026-10-13
|
|
99
|
+
|
|
100
|
+
See the [0.29.0 release record](https://github.com/Raizo-TCS/phronomy/releases/tag/v0.29.0).
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## [0.28.0] - 2026-10-09
|
|
105
|
+
|
|
106
|
+
The architecture notes below were already included in this release and carried
|
|
107
|
+
unchanged in the 0.29.0 changelog. They are retained from the former Unreleased
|
|
108
|
+
section and are not new 0.30.0 changes.
|
|
109
|
+
|
|
110
|
+
### r8 first implementation unit (breaking)
|
|
16
111
|
|
|
17
112
|
- Move Context policy/plan/manifest/budget/prompt operations into `Phronomy::Context`.
|
|
18
113
|
Agent retains snapshot, journal and lifecycle ownership. Manifest and execution
|
data/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
> This project is primarily developed and maintained by **AI coding agents**.
|
|
5
5
|
> As a result, `main` receives frequent, large, and unannounced changes.
|
|
6
6
|
> External contributors should expect significant churn and potential conflicts at any time.
|
|
7
|
+
> Correct responsibility boundaries and behavior take priority over backward compatibility.
|
|
8
|
+
> Obsolete APIs and compatibility-only paths are removed; update applications with the documented API changes.
|
|
7
9
|
> We apologise for the instability this may cause.
|
|
8
10
|
|
|
9
11
|
**Phronomy** is a Ruby AI agent framework for stateful Agents, Workflows, Tools,
|
|
@@ -35,10 +37,13 @@ tracking `main` directly.
|
|
|
35
37
|
|
|
36
38
|
See [Features and Application Programming Interface (API) stability](docs/features.md) for the full feature matrix.
|
|
37
39
|
|
|
38
|
-
The following application APIs are
|
|
40
|
+
The following application APIs are available as Beta in v0.30.0:
|
|
39
41
|
|
|
40
42
|
| API | Stability | Contract |
|
|
41
43
|
|---|---|---|
|
|
44
|
+
| `Phronomy::LLMAdapter::LMStudio` | Beta | Explicit known-output-error identification and bounded opt-in retry; [policy and evidence limits](docs/architecture/lm-studio-output-failures.md) |
|
|
45
|
+
| Agent `output_schema:`, `Agent::OutputError` and `OutputParser::JsonSchemaParser` | Beta | Agent returns validated immutable JSON or an explicit output failure; [contract and migration](docs/architecture/structured-output-and-scope.md) |
|
|
46
|
+
| `Phronomy::GeneratorVerifier`, its approval/lifetime operations and immutable `Result` with output-failure diagnostics | Beta | [Generation and structured-output contract](docs/architecture/structured-output-and-scope.md) |
|
|
42
47
|
| `Agent.open_scope`, `Agent::Scope`, `Agent::Base#unload_async / #unload!`, `AgentUnloadedError` and `Agent::ScopeCleanupError` | Beta | Runtime-bound ownership and safe release of idle Agent incarnations without changing saved history or closing the Store; [contract](docs/architecture/dx05-agent-scope.md) |
|
|
43
48
|
| `Workflow::Builder#task_state` and `WorkflowTaskResumeError` | Beta | State-entry-scoped Task completion, live cancellation and explicit restart rejection; [contract](docs/architecture/dx05-workflow-task-state.md) |
|
|
44
49
|
| `Phronomy::Integrations::OrderedEventDelivery` | Beta | Optional ordered delivery with bounded admission and explicit drain lifetime; [usage](docs/ordered-event-delivery.md) |
|
|
@@ -62,15 +67,21 @@ Then run:
|
|
|
62
67
|
bundle install
|
|
63
68
|
```
|
|
64
69
|
|
|
65
|
-
Phronomy
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
Phronomy requires RubyLLM 2.0.x. The tested minimum HTTP stack is Faraday
|
|
71
|
+
2.14.4 and faraday-net_http 3.4.4; newer versions within their respective major
|
|
72
|
+
versions are allowed. Both floors are explicit: raising Faraday alone can still
|
|
73
|
+
resolve an old Net::HTTP adapter that loses HTTP status during streaming.
|
|
74
|
+
CI checks fresh resolution and this exact pair with MCP 1.0.0. These are verified
|
|
75
|
+
support floors, not a claim about the first upstream release containing a fix.
|
|
76
|
+
See the
|
|
69
77
|
[RubyLLM 2 and token-ownership migration](docs/architecture/rubyllm-2-token-ownership.md)
|
|
70
78
|
for removed input-budget overrides and the in-flight Tool-manifest upgrade boundary.
|
|
71
79
|
|
|
72
80
|
Configure RubyLLM with the provider credentials and transport policy required by
|
|
73
|
-
your application.
|
|
81
|
+
your application. The default adapter delegates transport retry and timeout policy
|
|
82
|
+
to RubyLLM. The explicitly selected LMStudio backend instead disables SDK retries
|
|
83
|
+
and can retry one narrowly recognized generated-format failure at most once;
|
|
84
|
+
see its [policy](docs/architecture/lm-studio-output-failures.md).
|
|
74
85
|
|
|
75
86
|
```ruby
|
|
76
87
|
RubyLLM.configure do |c|
|
|
@@ -137,3 +137,11 @@ The published SVG is applied43-01. See the [naming boundary](entry-action-and-te
|
|
|
137
137
|
and the separate [open Tool schema finding](tool-schema-recording-gap.md).
|
|
138
138
|
|
|
139
139
|
Refactor 45 changes the token declarations as described in [the migration](rubyllm-2-token-ownership.md). Other Agent inheritance rules above remain unchanged. Tool schema/provider configuration follows the RubyLLM 2 inherited configuration contract.
|
|
140
|
+
|
|
141
|
+
## Agent iteration budget correction
|
|
142
|
+
|
|
143
|
+
`Agent.max_iterations` now bounds logical LLM calls per Agent execution, including
|
|
144
|
+
its first call and its final response. The nonnegative Integer limit is captured
|
|
145
|
+
at admission; zero permits no call. Tool count, approval/resume and backend HTTP
|
|
146
|
+
retries do not consume additional iterations. Declaration inheritance is unchanged.
|
|
147
|
+
See [the iteration-budget boundary and migration](agent-iteration-budget.md).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Agent iteration budget
|
|
2
|
+
|
|
3
|
+
## Problem and meaning
|
|
4
|
+
|
|
5
|
+
Agent previously converted `max_iterations` to the generic FSM transition limit
|
|
6
|
+
`12 + 8 * max_iterations`. A single-Tool round currently takes ten transitions;
|
|
7
|
+
parallel Tool completions add further transitions. Default ten therefore stopped
|
|
8
|
+
the ninth Tool round before the tenth LLM call. Approval/recovery also creates new
|
|
9
|
+
FSM sessions, so a session counter cannot enforce an execution-wide Agent limit.
|
|
10
|
+
|
|
11
|
+
`Agent.max_iterations = N` now permits at most N logical LLM calls in one
|
|
12
|
+
AgentExecution, including the first and final call. Tool execution, authorization,
|
|
13
|
+
approval, streaming chunks and backend HTTP retries consume no additional calls.
|
|
14
|
+
This does not bound physical HTTP attempts, tokens, elapsed time or Tool count.
|
|
15
|
+
|
|
16
|
+
## Owners and dependency direction
|
|
17
|
+
|
|
18
|
+
| Owner | Responsibility |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Application / Agent declaration | Choose the maximum logical LLM calls. |
|
|
21
|
+
| Agent::IterationBudget | Validate the limit and decide whether another call is allowed from AgentExecution.llm_calls. |
|
|
22
|
+
| Agent preparation operations | Check before context hooks and provider dispatch; capture the limit in execution metadata. |
|
|
23
|
+
| Agent execution/recovery record encoders | Existing durable call identity, result recording and exactly-once recovery interpretation. |
|
|
24
|
+
| Agent::EngineSessionBuilder / InvocationTransitions | Select generic Engine safety mode and a bound appropriate to the Agent phase graph. |
|
|
25
|
+
| Engine::FSMSession | Bound automatic transition chains, without knowing LLMs, Tools, Agent records or iteration policy. |
|
|
26
|
+
| LLMAdapter / RubyLLM backend | Existing logical-call contract, wire transport, response handling and SDK retry policy. |
|
|
27
|
+
|
|
28
|
+
There is no new mutable Agent counter and no persistence access from Engine.
|
|
29
|
+
The call records already used for context call sequence and recovery remain the
|
|
30
|
+
single authority. InitialPreparation checks before the first call. DispatchPreparation
|
|
31
|
+
includes pending runtime outcomes through the existing record encoder, checks the
|
|
32
|
+
resulting call count, then prepares and commits the next provider dispatch.
|
|
33
|
+
Existing durable pending-call identity prevents unknown outcomes from being
|
|
34
|
+
automatically redispatched. No counter is incremented by Tool or Engine events.
|
|
35
|
+
|
|
36
|
+
Engine's optional `recursion_limit_scope: :automatic_chain` counts consecutive
|
|
37
|
+
accepted `state_completed` transitions. Only an accepted external transition
|
|
38
|
+
starts a new chain; consumed/stale events or events without a transition do not.
|
|
39
|
+
Agent selects this mode with its declared phase count as the safety bound.
|
|
40
|
+
Engine's default `:session` mode retains the previous total-transition limit for
|
|
41
|
+
Workflow and Tool sessions. Total step count remains available for diagnostics.
|
|
42
|
+
This is a generic mechanism, not an Engine dependency on Agent policy.
|
|
43
|
+
|
|
44
|
+
ADR-066's allocation remains intact: Agent owns execution and recovery, C09 owns
|
|
45
|
+
one model operation, C06 owns Tool execution, and the backend owns SDK details.
|
|
46
|
+
No RubyLLM, provider-specific or example-specific code is added.
|
|
47
|
+
|
|
48
|
+
## Completion, suspension and compatibility
|
|
49
|
+
|
|
50
|
+
- The limit is a nonnegative Integer captured as `agent_max_iterations` in the
|
|
51
|
+
existing execution metadata at admission. Changing a class declaration during
|
|
52
|
+
approval cannot increase or reset the active run's budget. No DB schema migration.
|
|
53
|
+
- Resume/recovery uses the saved call records and saved limit. An older execution
|
|
54
|
+
without this metadata uses the current class limit and records it when preparing
|
|
55
|
+
another call. Its original limit cannot be reconstructed. Restart from legacy
|
|
56
|
+
initial preparation captures the fallback before input hooks.
|
|
57
|
+
- A new AgentExecution gets its own limit; handing work to another Agent gives
|
|
58
|
+
that Agent its own execution budget. GeneratorVerifier/SharedState orchestration
|
|
59
|
+
limits remain separate policies.
|
|
60
|
+
- A final response on call N succeeds. If call N requests Tools, those Tools
|
|
61
|
+
finish or await approval normally; the attempted next LLM call then fails with
|
|
62
|
+
the existing `Phronomy::RecursionLimitError`. Completed Tool results are retained;
|
|
63
|
+
no final answer or successful application outcome is fabricated.
|
|
64
|
+
- Zero dispatches no LLM call. Invalid limits fail before inference. Default ten
|
|
65
|
+
and declaration inheritance remain unchanged. Error class is retained; the
|
|
66
|
+
message now identifies the logical Agent limit rather than an FSM step limit.
|
|
67
|
+
|
|
68
|
+
This correction may allow more work than the old accidental FSM cutoff, or stop
|
|
69
|
+
an approval-heavy run previously able to reset its session counter. Deploy at a
|
|
70
|
+
quiescent Runtime boundary; do not hot-swap an active process. Application owners
|
|
71
|
+
must assess actual iteration needs after the counting bug is fixed. Increasing
|
|
72
|
+
example limits is not part of this change.
|
|
73
|
+
|
|
74
|
+
## Verification scope
|
|
75
|
+
|
|
76
|
+
Regression tests cover nine Tool rounds plus final call ten, streaming, a real
|
|
77
|
+
RubyLLM retry through stubbed HTTP, many Tools in one response, exact cutoff,
|
|
78
|
+
fresh execution, approval and fresh Runtime restoration, recovered provider/Tool
|
|
79
|
+
outcomes, legacy metadata, zero and invalid limits. Generic Engine tests cover
|
|
80
|
+
automatic loops, stale events and unchanged default session limits. Live LM Studio
|
|
81
|
+
acceptance and its independent peg-native parsing failure remain separate gates.
|
|
@@ -83,8 +83,9 @@ logs the Agent ID; it is never silently made creatable again.
|
|
|
83
83
|
|
|
84
84
|
Scope does not cancel or wait for unjoined child execution as an implicit
|
|
85
85
|
cleanup policy. An active Agent is retained and cleanup reports `AgentBusyError`.
|
|
86
|
-
If the main operation
|
|
87
|
-
|
|
86
|
+
If both the main operation and cleanup fail, ScopeCleanupError retains the original
|
|
87
|
+
exception as primary_error/cause and every cleanup failure, plus the retryable scope.
|
|
88
|
+
If cleanup succeeds, the original exception is re-raised with the same identity.
|
|
88
89
|
If the main operation succeeded, failed cleanup raises `Agent::ScopeCleanupError`
|
|
89
90
|
(`code: "agent.scope_cleanup_failed"`). `result` preserves the successful value;
|
|
90
91
|
`failures` is an array of `{agent_id:, error:}` with the original exceptions.
|
|
@@ -117,3 +118,9 @@ calling it does not opt into scope cleanup.
|
|
|
117
118
|
|
|
118
119
|
This is P5 (core). P6 migrates application examples and performs cross-repository
|
|
119
120
|
acceptance against the published or pinned candidate core.
|
|
121
|
+
|
|
122
|
+
## Structured-output lifetime update
|
|
123
|
+
|
|
124
|
+
Scope now exposes `release!` and retains only failed owners for retry. CleanupError
|
|
125
|
+
also carries scope, resolved result and primary_error. The exact Task/error/release
|
|
126
|
+
rules are specified in [structured output and scope](structured-output-and-scope.md).
|
|
@@ -52,16 +52,16 @@ that every possible backend failure has been injected.
|
|
|
52
52
|
| C01 | invoke/admission, TeamExecutionRepository.create_active/save/assert_idle!: active Team run | TeamBusyError with team_id and team.busy replaces AgentBusyError only for Team ownership. Child-Agent failures retain their own classes. No AgentBusy alias or inheritance. | execution_constraint_translation_spec; shared SQL coordination contract |
|
|
53
53
|
| C01 | HandoffRunner.invoke/cancel, Orchestrator fan-out, operation rejection | Retain ConfigurationError, HandoffError, StateConflictError, recovery requirements and on_error policy. Missing retained children are not missing Teams. Readback reconciliation may itself fail and does not prove absence. OperationRejected stays private; public code team.enqueue_after_finalize is unchanged. | durable_coordination_spec; integration/team_coordinator_spec; SQL reason diagnostics |
|
|
54
54
|
| C02 | Workflow definition/action, WorkflowContext writes, state CAS, waiting/resume | Retain ConfigurationError, WorkflowContextOwnershipError, WorkflowAsyncActionError and persistence conflict. Workflow has no equivalent target-root load API to justify another NotFound class. DX05-D adds WorkflowTaskResumeError with workflow.task_resume_unsupported only for unsupported restoration of a task-state phase, before any start side effect. Start/source/apply failures keep their original errors, and task cancellation remains distinct from a failed CancellationError. Agent scope is separate. | workflow and execution unit/integration suites; task_state_spec; shared SQL task-state contract (live PostgreSQL acceptance pending) |
|
|
55
|
-
| C03 | GeneratorVerifier.invoke;
|
|
55
|
+
| C03 | GeneratorVerifier.invoke; schema-qualified confidence decision | Agent owns OutputError; Generation records output_failed with its diagnostic; GeneratorVerifier::UnacceptedResultError carries Result and an optional code. CleanupError retains cleanup and primary failures. See generator-verifier-lifecycle-result.md. | generator_verifier specs; error_api_diagnostics_spec |
|
|
56
56
|
| C04 | Base.load, create/get, invoke/resume/purge | Add AgentNotFoundError only at the requested root. Journal/content/execution absence remains persistence failure. Preserve foreign AgentNotFound identity. AlreadyExists/Busy/Purged, uncertain purge and recovery-required retain their meaning. | error_api_boundaries_spec; Agent lifecycle/recovery suites |
|
|
57
57
|
| C04 | stream listener policy; result/failure persistence | StreamCallbackError keeps event_type/original_error/result, with optional code. Listener :fail_task versus :log_and_continue remains explicit; no unconditional callback swallowing. | stream_callback_error_policy_spec; error_api_diagnostics_spec |
|
|
58
58
|
| C05 | Assembly.prepare and policy invocation; plan/budget validation | Keep BudgetExceededError and ManifestError. Reuse C15 public trace_with, metadata only; a finish failure cannot mask policy failure or export the returned context. | error_api_boundaries_spec; Context suites |
|
|
59
59
|
| C06 | Tool.call / native async operation; schema, execution, async handle validity | Keep ToolError class; supply tool.invalid_arguments / tool.execution_failed / tool.invalid_async_result at owned conversion sites. Explicit async cause fixes delayed-failure information loss. Existing ToolError/cancellation pass through unchanged. :suppress survives logger failure. | tool/async_operation_spec; tool/base_spec; schema_error_spec |
|
|
60
60
|
| C07 | StorageBoundary, transaction, SaveOutcome, SnapshotComparison | Retain known-category mapping and original cause. Unknown I/O/application failures pass through. Keep committed/not_committed/unknown separately from exception class; no code-based reconciliation. | storage_boundary_spec; failure_contract_spec; snapshot_comparison_spec; SQL suites |
|
|
61
61
|
| C08 | fetch, fetch_text, fetch_json and content identity | Invalid requested JSON is IntegrityError with content.invalid_json and original ParserError; invalid UTF-8 is content.invalid_encoding. Raw fetch failures pass through; no dependency on OutputParser. Requesting JSON for plain text is also invalid representation, not proof of physical corruption. | error_api_boundaries_spec; content conformance; SQLite |
|
|
62
|
-
| C09 | LLM complete/stream, request/result checks, RubyLLM conversion |
|
|
62
|
+
| C09 | LLM complete/stream, request/result checks, RubyLLM conversion | Authentication/RateLimit remain TransportError children; ContextLength and InvalidResult remain separate. The RubyLLM backend also maps identified Faraday TimeoutError/ConnectionFailed to TransportError with the original cause chain. Unknown exceptions, cancellation/deadlines and callbacks (including same-class Faraday failures) retain identity. Classification does not imply retry safety. | LLMAdapter suites; transport_error unit and real-HTTP integration contracts |
|
|
63
63
|
| C10 | VectorStore add/search/remove/clear/size and AsyncClient | Keep InvalidResultError for invalid response and driver communication errors unchanged. Driver-specific transaction/effect uncertainty is not normalized without a backend-specific contract. No universal VectorStore TransportError or sibling-contract borrowing. | VectorStore and async-client suites; live PG/Redis pending |
|
|
64
|
-
| C11 | Embeddings.embed / AsyncClient; RubyLLM errors |
|
|
64
|
+
| C11 | Embeddings.embed / AsyncClient; RubyLLM errors | Owner-local AuthenticationError and RateLimitError remain under TransportError. Other RubyLLM errors and identified Faraday TimeoutError/ConnectionFailed map to TransportError in the concrete backend, preserving causes. Arbitrary I/O failures, cancellation/deadlines and programming errors are not guessed to be SDK failures. | error_api_boundaries_spec; embeddings/async_client_spec; transport_error unit and real-HTTP integration contracts |
|
|
65
65
|
| C12 | Records.read/fetch, conditions/unique constraints, streams/blobs, atomic views | Keep nil read versus raising fetch; preserve condition/resource/constraint. Add optional code to specialized constructors; SPI 2 and storage format unchanged. No Agent or Persistence semantics in the backend. | storage SPI snapshot; backend conformance; SQLite |
|
|
66
66
|
| C13 | TaskResult completion, map/flat_map/all_settled, wait/timeout/cancel | Transport errors unchanged. Observer failure leaves settled result intact and continues later observers even if logging fails. Transformation failure settles the derived task. Outcome attributes and physical completion remain separate. | task_result_spec; error_api_boundaries_spec; async composition suites |
|
|
67
67
|
| C15 | Base.trace, trace_with, OpenTelemetry.trace, Automatic | Explicit tracing propagates start/finish-only failure. After a primary business failure finish is attempted once and secondary report failure is suppressed. No finish after start failure. OpenTelemetry keeps with_span context. Automatic retains best-effort observation policy; Langfuse keeps its adapter-specific network suppression. | tracing/base_spec; open_telemetry_tracer_spec; automatic and extension specs |
|
|
@@ -211,7 +211,7 @@ Ripper inspected 339 Ruby files. The following 63 definitions include base, priv
|
|
|
211
211
|
| `Phronomy::SchedulerReentrancyError` | `Phronomy::EventLoopReentrancyError` | `lib/phronomy/execution/scheduler_reentrancy_error.rb` |
|
|
212
212
|
| `Phronomy::TimeoutError` | `Phronomy::Error` | `lib/phronomy/execution/timeout_error.rb` |
|
|
213
213
|
| `Phronomy::FilterBlockError` | `Phronomy::Error` | `lib/phronomy/filter/filter_block_error.rb` |
|
|
214
|
-
| `Phronomy::
|
|
214
|
+
| `Phronomy::GeneratorVerifier::UnacceptedResultError` | `Phronomy::Error` | `lib/phronomy/generation/generator_verifier/unaccepted_result_error.rb` |
|
|
215
215
|
| `Phronomy::Integrations::OrderedEventDelivery::ClosedError` | `Phronomy::Error` | `lib/phronomy/integrations/ordered_event_delivery.rb` |
|
|
216
216
|
| `Phronomy::Integrations::OrderedEventDelivery::OverflowError` | `Phronomy::Error` | `lib/phronomy/integrations/ordered_event_delivery.rb` |
|
|
217
217
|
| `Phronomy::LLMAdapter::AuthenticationError` | `Phronomy::LLMAdapter::TransportError` | `lib/phronomy/llm_adapter/authentication_error.rb` |
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# GeneratorVerifier: approval, lifetime and result contract
|
|
2
|
+
|
|
3
|
+
Generation (C03) is a responsibility group, not a Ruby namespace.
|
|
4
|
+
Phronomy::GeneratorVerifier is the public draft/review/retry API. Applications
|
|
5
|
+
choose the Agent classes, Tools, prompts, evaluation thresholds and authorization
|
|
6
|
+
policy. Generation owns composition and evaluation; Agent (C04) owns Tool
|
|
7
|
+
authorization, durable execution, cancellation and safe unload.
|
|
8
|
+
|
|
9
|
+
Correct behavior takes priority over backward compatibility. This change removes
|
|
10
|
+
trusted/trusted?, raise_if_untrusted and LowConfidenceError. There are no legacy
|
|
11
|
+
aliases or compatibility branches.
|
|
12
|
+
|
|
13
|
+
## Application operations
|
|
14
|
+
|
|
15
|
+
Construct with new or open. Construction acquires both owned Agents, synchronously;
|
|
16
|
+
a failure acquiring the second releases the first. Prepare the pipeline before
|
|
17
|
+
entering EventLoop. Both Agents and their conversations are reused between
|
|
18
|
+
invocations. open requires a block, returns its value, and always attempts release!.
|
|
19
|
+
A directly returned TaskResult is awaited once before release; arrays and nested
|
|
20
|
+
Tasks are not recursively awaited. See [structured output and scope](structured-output-and-scope.md).
|
|
21
|
+
|
|
22
|
+
invoke waits for the final Result. invoke_async returns TaskResult. A pipeline
|
|
23
|
+
admits one invocation at a time; independent concurrent conversations need
|
|
24
|
+
independent pipelines. Workflow state, approvals and cancellation are per invocation.
|
|
25
|
+
config is forwarded to Workflow. Only the private cancellation token and any
|
|
26
|
+
InvocationContext are forwarded to Agent operations, not Workflow-specific
|
|
27
|
+
identity or settings.
|
|
28
|
+
|
|
29
|
+
on_approval receives an Approval with invocation_id, phase (:draft/:review) and
|
|
30
|
+
request (Agent::ToolApprovalRequest). It is a short, thread-safe notification,
|
|
31
|
+
not a blocking UI callback or a function whose return value authorizes a Tool.
|
|
32
|
+
Use approval.respond_async(approved: true/false), or enqueue the Approval for an
|
|
33
|
+
external UI to answer later. The response Task observes the resumed Agent's
|
|
34
|
+
terminal outcome and returns nil. Do not wait for it inside the callback.
|
|
35
|
+
|
|
36
|
+
Without a callback, approval_requests exposes notifications issued in the current
|
|
37
|
+
invocation, including answered ones. It is not a mirror of current durable
|
|
38
|
+
approval state. Suspension is not an error and no implicit approval or denial is
|
|
39
|
+
performed. Expiry and cancellation are application choices. Stale invocation
|
|
40
|
+
handles fail; Agent validates execution/request identity and duplicate decisions.
|
|
41
|
+
Invalid replies fail their own Task without cancelling the original invocation.
|
|
42
|
+
Callback exceptions cancel the owned invocation and remain its primary error.
|
|
43
|
+
|
|
44
|
+
cancel_async requests cancellation without mutating a caller-owned cancellation
|
|
45
|
+
token. It can also address a known Agent execution after a Handoff outcome.
|
|
46
|
+
Completion acknowledges the cancellation operations, not physical quiescence;
|
|
47
|
+
observe the invocation result separately. release! delegates safety to Agent's
|
|
48
|
+
unload!, preserves saved history and does not close the Store. It rejects active
|
|
49
|
+
invocations rather than cancelling or denying approvals implicitly.
|
|
50
|
+
|
|
51
|
+
All owners are attempted during release. Successful owners are removed; failed
|
|
52
|
+
ones remain available for cancellation or another release attempt. Partial release
|
|
53
|
+
cannot be followed by a new invocation. Successful release is idempotent (true,
|
|
54
|
+
then false). CleanupError exposes pipeline, failures, result and primary_error;
|
|
55
|
+
when both application work and cleanup fail, neither exception nor the recovery
|
|
56
|
+
handle is lost. Its cause is the primary exception, if present.
|
|
57
|
+
|
|
58
|
+
Handoff coordination is outside this composition's contract. A Handoff result
|
|
59
|
+
raises generation.unsupported_handoff rather than leaving the Workflow pending.
|
|
60
|
+
Agent retains authority over durable coordination and safe release; Generation
|
|
61
|
+
never purges unfinished work or clears retention to make cleanup appear successful.
|
|
62
|
+
Reconstructing an in-flight GeneratorVerifier after process restart is not offered.
|
|
63
|
+
|
|
64
|
+
## Agent cancellation during approval suspension
|
|
65
|
+
|
|
66
|
+
An approval suspension ends the current FSM session, but the logical execution
|
|
67
|
+
and its original Task remain pending. C04 now retains the cancellation connection
|
|
68
|
+
through this suspension, routes cancellation to its existing quiescence/terminal
|
|
69
|
+
commit barrier, and closes the subscription on resume or termination. Generation
|
|
70
|
+
does not implement this Agent transition itself. Cancellation and approval racing
|
|
71
|
+
at the suspension boundary must not create competing terminal/resume commits.
|
|
72
|
+
|
|
73
|
+
## Results and decisions
|
|
74
|
+
|
|
75
|
+
Result is immutable, including nested data. It contains output, confidence,
|
|
76
|
+
confidence_threshold, review_approved, citations, iterations, review_notes,
|
|
77
|
+
termination_reason, interrupted_phase and failure. accepted? describes satisfaction of the
|
|
78
|
+
configured evaluation conditions, not an application's decision to publish.
|
|
79
|
+
|
|
80
|
+
Confidence is the lower final draft/review score. A completed evaluation is accepted
|
|
81
|
+
only when review_approved is true and confidence meets the threshold. At the
|
|
82
|
+
iteration limit, acceptance wins if both conditions hold; otherwise the reason is
|
|
83
|
+
iteration_limit. Scores and threshold are finite 0..1; max_iterations is a positive
|
|
84
|
+
Integer. Agent validates the fixed output schema without fallback or normalization.
|
|
85
|
+
|
|
86
|
+
A Tool denial is a normal Agent rejected outcome, not a parser input or automatic
|
|
87
|
+
retry. Result reports tool_rejected and the interrupted phase. Confidence and
|
|
88
|
+
review_approved are nil because the evaluation did not complete. Rejection during
|
|
89
|
+
draft has no output; rejection during review retains the draft. iterations counts
|
|
90
|
+
completed drafts.
|
|
91
|
+
|
|
92
|
+
to_h includes all fields. Result.from_h accepts that Hash and its JSON round trip,
|
|
93
|
+
rejecting unknown fields, invalid types and contradictory reasons. Citation keys
|
|
94
|
+
are normalized to strings. Equality and hash use all semantic fields, so a change
|
|
95
|
+
in review decision or threshold is observable. Applications own storage/transport
|
|
96
|
+
choices and any intentional projection of these fields.
|
|
97
|
+
|
|
98
|
+
raise_if_unaccepted defaults to false. When explicitly true, an unaccepted Result
|
|
99
|
+
raises GeneratorVerifier::UnacceptedResultError with result and code. Provider,
|
|
100
|
+
cancellation and callback errors do not become evaluation failures. An Agent
|
|
101
|
+
OutputError becomes output_failed with its phase and diagnostic; there is no automatic
|
|
102
|
+
retry. raise_if_unaccepted preserves that OutputError as the cause.
|
|
103
|
+
|
|
104
|
+
## Ownership boundaries
|
|
105
|
+
|
|
106
|
+
C03 depends on C04 Agent, C02 Workflow and C13 Execution. C04 uses C17
|
|
107
|
+
OutputParser to implement its output promise; C03 has no C17 dependency. Cancellation subscriptions use the existing execution abstraction.
|
|
108
|
+
No Agent registry, private Scope construction, Storage operation or Engine
|
|
109
|
+
implementation is accessed from Generation.
|
|
110
|
+
|
|
111
|
+
Private AgentOperation connects public Agent commands and notifications.
|
|
112
|
+
Invocation owns one call's child observations, subscription lifetime and approval
|
|
113
|
+
routing. WorkflowBuilder/AgentResultReceiver/PipelineState retain graph, event
|
|
114
|
+
conversion and correlated state application. Result owns evaluation facts and
|
|
115
|
+
their invariants.
|
|
116
|
+
|
|
117
|
+
## Application migration
|
|
118
|
+
|
|
119
|
+
Use open around the complete application operation, including validation retries.
|
|
120
|
+
Use accepted? and termination_reason, not score-only trusted?. For an external
|
|
121
|
+
approval UI, start invoke_async, enqueue on_approval notifications, respond through
|
|
122
|
+
the original Approval handle, and observe the final Task before release.
|
|
123
|
+
|
|
124
|
+
examples/19_trust_pipeline is the direct consumer. examples/27_issue_analyzer only
|
|
125
|
+
mentions GeneratorVerifier in descriptive classification text and requires no API
|
|
126
|
+
migration. Full old/new runnable sources are available through the source diff.
|
|
@@ -1,111 +1,20 @@
|
|
|
1
1
|
# GeneratorVerifier ownership and event contract
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| GeneratorVerifier | Public settings and Result; cached Workflow assembly, invocation, default JSON parser fallbacks and final confidence/raise policy. |
|
|
22
|
-
| GeneratorVerifier::WorkflowBuilder | Draft/review/finalize/failed graph, request IDs, prompt creation, Agent startup and convergence guard. |
|
|
23
|
-
| GeneratorVerifier::AgentResultReceiver | Separate draft/review payload conversion, common terminal-event classification and failure notification to the supplied Workflow. |
|
|
24
|
-
| GeneratorVerifier::PipelineState | Existing Workflow fields, request correlation, stale/duplicate rejection and EventLoop-owned state mutation. |
|
|
25
|
-
|
|
26
|
-
The last three constants are private. WorkflowBuilder and AgentResultReceiver
|
|
27
|
-
are new internal classes; PipelineState is the existing class moved with its
|
|
28
|
-
body and canonical name unchanged. The implementation lives in three files under
|
|
29
|
-
generation/generator_verifier. The public facade and Result keep their names and
|
|
30
|
-
locations; no loader changes or compatibility aliases are introduced.
|
|
31
|
-
|
|
32
|
-
The initial D08 sketch suggested multi_agent/generator_verifier_workflow.rb.
|
|
33
|
-
Since the prior layout work established generation as this pattern's owner,
|
|
34
|
-
the internal files now stay there instead of creating a second feature owner.
|
|
35
|
-
The new directory adds a module in directory-based analysis, not a public API.
|
|
36
|
-
|
|
37
|
-
WorkflowBuilder#build reads as a graph: named entries, then ordered transitions.
|
|
38
|
-
start_draft/start_review describe request preparation and dispatch. The receiver's
|
|
39
|
-
draft_payload and review_payload retain different meanings. Their common listener
|
|
40
|
-
has only the two internally selected phases; it is not a public configurable
|
|
41
|
-
pipeline. It shares the same terminal/error rules rather than combining response
|
|
42
|
-
formats into an options-driven generic parser.
|
|
43
|
-
|
|
44
|
-
Default parsers remain explicit callables captured by the facade. Clamp and
|
|
45
|
-
citation normalization move to their receiver owner. The old __send__ calls back
|
|
46
|
-
to facade helpers disappear. The existing private Agent event-sink entry point
|
|
47
|
-
is still called via send; changing that cooperation API is outside this scope.
|
|
48
|
-
|
|
49
|
-
## Preserved ordering and failure contract
|
|
50
|
-
|
|
51
|
-
- Each Agent is constructed once, lazily during the first successful Workflow
|
|
52
|
-
build. The cached Workflow and Agent instances are reused. Each invoke gets a
|
|
53
|
-
fresh Workflow context. No locking or new concurrency policy is introduced.
|
|
54
|
-
- Each request gets a new UUID and a merged context before prompt construction.
|
|
55
|
-
The listener captures that request ID and the context's stable Workflow ID.
|
|
56
|
-
Workflow closures see the completed Workflow assignment before any entry runs.
|
|
57
|
-
- Entry actions start asynchronous Agent work and return next_state, never a
|
|
58
|
-
TaskResult. Inline completion remains valid because signal queues a Workflow
|
|
59
|
-
event. Unknown/nonterminal Agent events are ignored.
|
|
60
|
-
- done parses output, normalizes the phase-specific payload and signals the
|
|
61
|
-
matching completed event. StandardError from parsing, normalization or success
|
|
62
|
-
notification is signalled as the corresponding failed event with the same
|
|
63
|
-
exception object. Failure-notification exceptions are not retried or wrapped.
|
|
64
|
-
- error/timeout/cancelled use the payload error or the same phase-specific
|
|
65
|
-
fallback message. approval_required remains a pipeline failure. A false return
|
|
66
|
-
from signal is returned without a retry or a new failure event.
|
|
67
|
-
- PipelineState accepts only the current request ID. It clears the accepted ID,
|
|
68
|
-
increments iteration after draft completion, appends feedback after review,
|
|
69
|
-
and consumes old/duplicate results before any transition. The receiver does
|
|
70
|
-
not mutate context or add its own deduplication; stale done payloads can still
|
|
71
|
-
be parsed before the state rejects their correlated event.
|
|
72
|
-
- Review completes when both the lower normalized score meets threshold and
|
|
73
|
-
approval is literal true, or when the iteration limit has been reached.
|
|
74
|
-
Otherwise it returns to draft and passes the last feedback to its prompt.
|
|
75
|
-
- Final Result trust remains confidence >= threshold. At the iteration limit,
|
|
76
|
-
high confidence with approved=false can therefore still produce trusted=true.
|
|
77
|
-
A nonpositive limit still executes one draft/review cycle. These are observed
|
|
78
|
-
existing semantics, not behavior fixes hidden in this extraction.
|
|
79
|
-
|
|
80
|
-
Public initialize/invoke parameters, Result fields/trusted? alias, parser
|
|
81
|
-
fallbacks, score/citation normalization, error messages and PipelineState fields
|
|
82
|
-
remain unchanged. Agent/Workflow/Engine/Storage behavior and SQL are not modified.
|
|
83
|
-
Private clamp/normalize_citations implementations relocate; private overrides are
|
|
84
|
-
not treated as additional supported public APIs.
|
|
85
|
-
|
|
86
|
-
## Verification and trade-off
|
|
87
|
-
|
|
88
|
-
Thirty-nine behavior examples pass unchanged on Refactor 40 and the candidate.
|
|
89
|
-
They cover inline completion, ignored progress, pending Task returns, both phases'
|
|
90
|
-
error/timeout/cancelled/approval failures, parser and notification failures,
|
|
91
|
-
request correlation, duplicate/old callbacks, clamping, literal approval, final
|
|
92
|
-
trust, iteration limits, caching, fresh state and config forwarding. Existing
|
|
93
|
-
delayed-callback and WebMock integration examples cover the real Workflow path.
|
|
94
|
-
|
|
95
|
-
A separate process comparison preserves public methods, parameters, constants,
|
|
96
|
-
Result shape, the private state name/field schema/defaults and Runtime inactivity.
|
|
97
|
-
Stable/Beta snapshots do not list GeneratorVerifier, so this explicit comparison
|
|
98
|
-
supplements those existing gates. Core/integration/examples/real SQLite, type,
|
|
99
|
-
style, annotations and isolated gem checks are included in distribution evidence.
|
|
100
|
-
Live PostgreSQL, live LLM, candidate CI and performance are not run for this scope.
|
|
101
|
-
|
|
102
|
-
The facade is 369 -> 118 lines. Workflow definition is 199 -> 34 lines, with a
|
|
103
|
-
12-line facade assembly method. The three internal files are 112/89/57 lines,
|
|
104
|
-
for 376 total, seven more than before. Two new classes and one moved class cost
|
|
105
|
-
additional files; they give graph, receiver and state independent reading units.
|
|
106
|
-
Directory-level dependency counts increase with that physical partition; cycle
|
|
107
|
-
membership is unchanged. This is responsibility separation, not cycle removal.
|
|
108
|
-
|
|
109
|
-
Refactor 41 is applied and independently verified at core e87eb77f, tree
|
|
110
|
-
14dc8a546a4fd96e19e0713f7480ca2efa3c331a. All nine files and the full tree match.
|
|
111
|
-
R08/D08 is closed. The published diagram is applied41-01. R09 and R10 remain.
|
|
3
|
+
The current contract is
|
|
4
|
+
[GeneratorVerifier: approval, lifetime and result](generator-verifier-lifecycle-result.md).
|
|
5
|
+
|
|
6
|
+
GeneratorVerifier is the public owner of draft/review Agent composition and its
|
|
7
|
+
evaluation Result. AgentOperation delegates to public Agent commands. Invocation
|
|
8
|
+
owns per-call approval routing, cancellation subscriptions and child observations.
|
|
9
|
+
WorkflowBuilder builds the graph; AgentResultReceiver converts results;
|
|
10
|
+
PipelineState applies correlated events; Result owns immutable evaluation facts.
|
|
11
|
+
|
|
12
|
+
Both owned Agents are acquired at pipeline construction and reused until release.
|
|
13
|
+
Workflow contexts are fresh for each invocation. Concurrent use of one pipeline
|
|
14
|
+
is rejected. Approval suspension remains pending and is exposed to the application;
|
|
15
|
+
it is not converted to failure. Tool denial is a tool_rejected Result.
|
|
16
|
+
Handoff is explicitly unsupported instead of silently leaving completion pending.
|
|
17
|
+
|
|
18
|
+
The older R08/D08 and R8 unit15 documents record the historical extraction. Their
|
|
19
|
+
preserved score-only trust, approval-failure and lazy Agent acquisition behavior
|
|
20
|
+
has been superseded by the current contract.
|