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.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +3 -4
  3. data/CHANGELOG.md +200 -10
  4. data/CONTRIBUTING.md +81 -9
  5. data/README.md +15 -6
  6. data/VERIFY.sh +587 -0
  7. data/benchmark/bench_agent_invoke.rb +2 -2
  8. data/benchmark/bench_context_assembler.rb +39 -68
  9. data/benchmark/bench_regression.rb +2 -2
  10. data/docs/architecture/agent-context.md +174 -0
  11. data/docs/architecture/before-llm-input.md +78 -0
  12. data/docs/architecture/context-management.md +232 -0
  13. data/docs/architecture/knowledge-and-rag.md +130 -0
  14. data/docs/architecture/multi-agent-handoff.md +152 -0
  15. data/docs/architecture/persistence.md +175 -0
  16. data/docs/architecture/removed/agent-context.md +72 -0
  17. data/docs/architecture/security-boundaries.md +173 -0
  18. data/docs/architecture/tracing.md +194 -0
  19. data/docs/architecture.md +82 -0
  20. data/docs/archive/design/archived/04_api_design.md +507 -0
  21. data/docs/archive/design/archived/09_guardrails.md +186 -0
  22. data/docs/archive/design/archived/17_rails_integration.md +175 -0
  23. data/docs/archive/design/historical/00_design_philosophy.md +122 -0
  24. data/docs/archive/design/historical/01_rubyllm_evaluation.md +178 -0
  25. data/docs/archive/design/historical/06_design_decisions.md +143 -0
  26. data/docs/changelog/0.14-and-earlier.md +1 -1
  27. data/docs/decisions/001-rubyllm-as-provider-layer.md +6 -1
  28. data/docs/decisions/002-workflow-context-immutability.md +26 -1
  29. data/docs/decisions/006-no-built-in-guardrails.md +2 -1
  30. data/docs/decisions/012-canonical-execution-log-and-context-policy.md +120 -38
  31. data/docs/decisions/014-unified-persistence-durable-state.md +9 -2
  32. data/docs/decisions/016-semantic-multi-agent-handoff.md +112 -0
  33. data/docs/decisions/017-design-authority-and-adr-governance.md +200 -0
  34. data/docs/decisions/018-durability-guarantees-and-failure-model.md +488 -0
  35. data/docs/decisions/019-filter-contract-and-security-boundaries.md +229 -0
  36. data/docs/decisions/020-canonical-workflow-instance-identity.md +177 -0
  37. data/docs/decisions/021-generic-agent-invocation-identity-removal.md +119 -0
  38. data/docs/decisions/022-agent-execution-parent-identity-and-runtime-routing-boundary.md +193 -0
  39. data/docs/decisions/023-fsm-session-incarnation-identity-and-routing.md +139 -0
  40. data/docs/decisions/024-event-loop-single-writer-agent-runtime.md +188 -0
  41. data/docs/decisions/025-process-local-agent-ownership-and-runtime-admission.md +249 -0
  42. data/docs/decisions/026-workflow-runtime-admission-and-durable-terminal-barrier.md +257 -0
  43. data/docs/decisions/027-llm-adapter-provider-boundary.md +93 -0
  44. data/docs/decisions/README.md +172 -0
  45. data/docs/features.md +31 -11
  46. data/docs/getting-started.md +77 -45
  47. data/docs/migrations/0.19.md +14 -7
  48. data/docs/migrations/0.22.md +390 -0
  49. data/docs/persistence-backends.md +88 -38
  50. data/docs/runtime-and-concurrency.md +227 -33
  51. data/examples/README.md +13 -0
  52. data/lib/phronomy/agent/agent_execution.rb +19 -15
  53. data/lib/phronomy/agent/agent_invocation.rb +288 -93
  54. data/lib/phronomy/agent/agent_invocation_session_builder.rb +236 -202
  55. data/lib/phronomy/agent/agent_root.rb +3 -3
  56. data/lib/phronomy/agent/approval_evaluation_request.rb +37 -19
  57. data/lib/phronomy/agent/async_event_api.rb +145 -72
  58. data/lib/phronomy/agent/base.rb +388 -181
  59. data/lib/phronomy/agent/concerns/before_llm_input.rb +1 -1
  60. data/lib/phronomy/agent/context_assembler.rb +437 -178
  61. data/lib/phronomy/agent/context_candidate_resolver.rb +2 -2
  62. data/lib/phronomy/agent/context_plan.rb +18 -13
  63. data/lib/phronomy/agent/context_plan_validator.rb +246 -88
  64. data/lib/phronomy/agent/context_policies/default.rb +123 -34
  65. data/lib/phronomy/agent/context_policy.rb +109 -3
  66. data/lib/phronomy/agent/context_policy_input.rb +244 -0
  67. data/lib/phronomy/agent/context_policy_input_builder.rb +241 -0
  68. data/lib/phronomy/agent/execution_coordinator.rb +1975 -587
  69. data/lib/phronomy/agent/journal_record.rb +17 -4
  70. data/lib/phronomy/agent/llm_input_build_context.rb +1 -1
  71. data/lib/phronomy/agent/llm_input_manifest.rb +277 -2
  72. data/lib/phronomy/agent/llm_operation_result.rb +12 -7
  73. data/lib/phronomy/agent/phase_machine_builder.rb +19 -7
  74. data/lib/phronomy/agent/provider_call_outcome.rb +23 -7
  75. data/lib/phronomy/agent/recovery_coordinator/continuation.rb +271 -0
  76. data/lib/phronomy/agent/recovery_coordinator/installation.rb +427 -0
  77. data/lib/phronomy/agent/recovery_coordinator/resolution.rb +635 -0
  78. data/lib/phronomy/agent/recovery_coordinator.rb +211 -0
  79. data/lib/phronomy/agent/recovery_support.rb +512 -0
  80. data/lib/phronomy/agent/ruby_llm_materializer.rb +22 -13
  81. data/lib/phronomy/agent/selection/candidate.rb +53 -0
  82. data/lib/phronomy/agent/selection/constraint.rb +49 -0
  83. data/lib/phronomy/agent/shared_state.rb +38 -1
  84. data/lib/phronomy/agent/tool_approval_request.rb +33 -5
  85. data/lib/phronomy/agent/tool_definition_set.rb +49 -3
  86. data/lib/phronomy/agent/tool_invocation.rb +336 -102
  87. data/lib/phronomy/agent/tool_invocation_session_builder.rb +49 -45
  88. data/lib/phronomy/agent.rb +20 -2
  89. data/lib/phronomy/agent_already_exists_error.rb +5 -0
  90. data/lib/phronomy/agent_purged_error.rb +5 -0
  91. data/lib/phronomy/engine/concurrency/offload_pool.rb +17 -3
  92. data/lib/phronomy/engine/concurrency/physical_completion_task.rb +135 -0
  93. data/lib/phronomy/engine/event_loop.rb +622 -63
  94. data/lib/phronomy/engine/fsm_session.rb +194 -21
  95. data/lib/phronomy/engine/runtime/agent_ownership_registry.rb +352 -0
  96. data/lib/phronomy/engine/runtime.rb +77 -20
  97. data/lib/phronomy/generator_verifier.rb +12 -14
  98. data/lib/phronomy/invocation_context.rb +9 -29
  99. data/lib/phronomy/multi_agent/admission_registry.rb +51 -0
  100. data/lib/phronomy/multi_agent/coordination_state.rb +18 -0
  101. data/lib/phronomy/multi_agent/coordinator.rb +154 -0
  102. data/lib/phronomy/multi_agent/execution_coordinator.rb +116 -0
  103. data/lib/phronomy/multi_agent/fan_out_invocation.rb +24 -33
  104. data/lib/phronomy/multi_agent/fan_out_session_builder.rb +12 -19
  105. data/lib/phronomy/multi_agent/handoff.rb +24 -45
  106. data/lib/phronomy/multi_agent/handoff_capability_factory.rb +87 -0
  107. data/lib/phronomy/multi_agent/handoff_context.rb +95 -0
  108. data/lib/phronomy/multi_agent/handoff_policy.rb +137 -0
  109. data/lib/phronomy/multi_agent/handoff_projection.rb +191 -0
  110. data/lib/phronomy/multi_agent/handoff_request.rb +45 -0
  111. data/lib/phronomy/multi_agent/orchestrator.rb +12 -15
  112. data/lib/phronomy/multi_agent/runner.rb +98 -0
  113. data/lib/phronomy/persistence/durable_codec.rb +646 -0
  114. data/lib/phronomy/persistence/durable_record.rb +117 -0
  115. data/lib/phronomy/persistence/in_memory.rb +210 -134
  116. data/lib/phronomy/persistence/migration/initial_format_migration.rb +226 -0
  117. data/lib/phronomy/persistence/repository_facades.rb +316 -0
  118. data/lib/phronomy/persistence.rb +81 -41
  119. data/lib/phronomy/recovery.rb +186 -0
  120. data/lib/phronomy/testing/persistence_contract/a_journal_repository.rb +2 -2
  121. data/lib/phronomy/testing/persistence_contract/a_persistence_backend.rb +1 -1
  122. data/lib/phronomy/testing/persistence_contract/a_workflow_state_repository.rb +19 -19
  123. data/lib/phronomy/testing/persistence_contract/an_agent_repository.rb +3 -3
  124. data/lib/phronomy/testing/persistence_contract/an_execution_repository.rb +5 -5
  125. data/lib/phronomy/tracing/automatic.rb +176 -0
  126. data/lib/phronomy/tracing/base.rb +11 -2
  127. data/lib/phronomy/tracing/langfuse_tracer.rb +20 -12
  128. data/lib/phronomy/version.rb +1 -1
  129. data/lib/phronomy/workflow.rb +3 -6
  130. data/lib/phronomy/workflow_context.rb +14 -5
  131. data/lib/phronomy/workflow_recovery.rb +123 -0
  132. data/lib/phronomy/workflow_runner.rb +468 -256
  133. data/lib/phronomy.rb +6 -0
  134. data/scripts/api_snapshot.rb +12 -0
  135. data/sig/phronomy/agent.rbs +209 -7
  136. data/sig/phronomy/multi_agent.rbs +39 -0
  137. data/sig/phronomy/persistence.rbs +62 -4
  138. data/sig/phronomy/runtime.rbs +1 -4
  139. data/sig/phronomy/workflow.rbs +2 -2
  140. data/sig/phronomy.rbs +10 -0
  141. metadata +65 -17
  142. data/examples/workflows/agent_event_mapping.rb +0 -101
  143. data/examples/workflows/generic_task_event_mapping.rb +0 -66
  144. data/lib/phronomy/agent/activation_registry.rb +0 -28
  145. data/lib/phronomy/agent/agent_execution_activation.rb +0 -172
  146. data/lib/phronomy/agent/context_candidate.rb +0 -47
  147. data/lib/phronomy/agent/context_parts/budget/token_budget_packer.rb +0 -53
  148. data/lib/phronomy/agent/context_parts/requirements/required_context_resolver.rb +0 -56
  149. data/lib/phronomy/agent/context_parts/selectors/recent_first_selector.rb +0 -30
  150. data/lib/phronomy/agent/context_parts/unit_builders/dependency_aware_unit_builder.rb +0 -118
  151. data/lib/phronomy/agent/context_policy_descriptor.rb +0 -49
  152. data/lib/phronomy/agent/context_policy_registry.rb +0 -46
  153. data/lib/phronomy/agent/context_request.rb +0 -35
  154. data/lib/phronomy/agent/context_selection_unit.rb +0 -38
  155. data/lib/phronomy/agent/derived_content_spec.rb +0 -34
  156. data/lib/phronomy/agent/runner.rb +0 -97
@@ -0,0 +1,194 @@
1
+ > **CURRENT explanatory architecture**
2
+ >
3
+ > This document describes the reconciled current Phronomy system. Normative
4
+ > architecture decisions remain in the [ADR index](../decisions/README.md);
5
+ > source/runtime behavior remains implementation reality and does not silently
6
+ > amend an ADR.
7
+
8
+ # Tracing and Observability
9
+
10
+ ## 1. Scope
11
+
12
+ Phronomy provides a public custom-tracer SPI plus a deliberately small set of
13
+ Framework-owned automatic logical-operation spans.
14
+
15
+ Tracing is observability. It is not execution authority, domain identity,
16
+ Persistence durability, or a distributed tracing coordinator.
17
+
18
+ ## 2. Public tracer extension SPI
19
+
20
+ `Phronomy::Tracing::Base` defines the extension boundary:
21
+
22
+ ```ruby
23
+ start_span(name, input: nil, **metadata)
24
+ finish_span(span, output: nil, usage: nil, error: nil)
25
+ trace(name, input: nil, **metadata) { |span| ... }
26
+ ```
27
+
28
+ Configured tracer instances may receive calls concurrently from independent
29
+ Phronomy operations. Custom tracers must protect any mutable shared state they
30
+ own and must not assume OS-thread, EventLoop, or OffloadPool affinity.
31
+
32
+ Phronomy ships no-op, Langfuse, and OpenTelemetry tracer implementations. Adapter
33
+ behavior must be distinguished from Framework-wide guarantees.
34
+
35
+ ## 3. Automatic logical-operation coverage
36
+
37
+ Framework automatic tracing is intentionally limited to:
38
+
39
+ ```text
40
+ agent.execution
41
+ workflow.execution
42
+ llm.call
43
+ tool.execute
44
+ multi_agent.turn
45
+ ```
46
+
47
+ Internal steps such as ContextPolicy execution, Context assembly, Persistence
48
+ transactions, EventLoop dispatch, OffloadPool work, and FSM transitions are not
49
+ part of the standard automatic span topology.
50
+
51
+ Applications may add custom tracing independently.
52
+
53
+ ## 4. Sync/async parity
54
+
55
+ Automatic span semantics attach to the logical operation, not to the public
56
+ blocking facade method.
57
+
58
+ ```text
59
+ invoke / invoke_async
60
+ stream / stream_async
61
+ |
62
+ v
63
+ same logical Agent operation
64
+ |
65
+ v
66
+ agent.execution
67
+ ```
68
+
69
+ The same principle applies to Workflow run/resume operations.
70
+
71
+ ## 5. Span lifetimes
72
+
73
+ ### `agent.execution`
74
+
75
+ One active Agent run/resume segment.
76
+
77
+ The span starts after `execution_id` has been established and the active segment
78
+ is about to run. It ends when that segment's caller-facing Task settles.
79
+
80
+ Suspension closes the active span. Later approval/recovery continuation creates a
81
+ new `agent.execution` span correlated by the same logical `execution_id`.
82
+
83
+ Phronomy does not keep one span open for the full durable lifetime of an Agent
84
+ execution.
85
+
86
+ ### `workflow.execution`
87
+
88
+ One Workflow run/resume operation, ending with that operation's Task settlement.
89
+ The durable identity is `workflow_instance_id`.
90
+
91
+ ### `llm.call`
92
+
93
+ One Provider Call after `llm_call_id` assignment. Streaming chunks do not create
94
+ separate spans.
95
+
96
+ ### `tool.execute`
97
+
98
+ One authorized physical Tool execution. Approval waiting time is outside this
99
+ span.
100
+
101
+ ### `multi_agent.turn`
102
+
103
+ One coarse `MultiAgent::Runner` user turn. Handoff does not create a mandatory
104
+ long-lived span type.
105
+
106
+ ## 6. Correlation and identity
107
+
108
+ Portable Phronomy correlation uses existing purpose-specific semantic metadata,
109
+ for example:
110
+
111
+ ```text
112
+ agent_id
113
+ execution_id
114
+ llm_call_id
115
+ tool_invocation_id
116
+ tool_call_id
117
+ workflow_instance_id
118
+ task_id / parent_task_id
119
+ ```
120
+
121
+ Phronomy does not add a second tracing identity hierarchy or restore generic
122
+ Agent `thread_id`/`session_id`.
123
+
124
+ `InvocationContext#tracer_span` is not part of the current API.
125
+
126
+ ## 7. Parent/child semantics
127
+
128
+ Phronomy does not define a custom `TraceContext`, `SpanContext`, `parent_span`
129
+ API, EventLoop span registry, or durable span state.
130
+
131
+ A backend such as OpenTelemetry may preserve natural lexical nesting where its
132
+ own context is active. That adapter behavior does not establish a Phronomy-wide
133
+ guarantee that automatic spans form one backend-native parent/child tree across
134
+ Task/EventLoop/Offload/Runtime boundaries.
135
+
136
+ ## 8. `trace_pii`
137
+
138
+ For Framework-owned automatic spans, `trace_pii: false` prevents traced payload
139
+ content and sensitive exception detail from being exposed to the tracer.
140
+
141
+ The automatic boundary redacts/omits:
142
+
143
+ - Agent/LLM input and output payloads;
144
+ - Tool argument/result payloads;
145
+ - transferred textual payload where recorded;
146
+ - exception message/backtrace; and
147
+ - selected sensitive caller metadata fields.
148
+
149
+ Structural operation metadata, purpose-specific semantic IDs, status/error
150
+ class/category, and token usage may remain observable.
151
+
152
+ Automatic instrumentation does not copy arbitrary Application metadata
153
+ wholesale.
154
+
155
+ ## 9. Automatic tracing failure policy
156
+
157
+ Framework-owned automatic tracing is best-effort. A tracer failure during
158
+ automatic `start_span`/`finish_span` is warning-only where possible and does not
159
+ change the logical Agent/Workflow/LLM/Tool/Multi-Agent result.
160
+
161
+ This guarantee is specific to Framework automatic instrumentation. It does not
162
+ redefine the behavior of Application code that directly calls the public
163
+ `Tracing::Base#trace` template method.
164
+
165
+ ## 10. TokenUsage
166
+
167
+ `Phronomy::TokenUsage` has four fields:
168
+
169
+ ```text
170
+ input
171
+ output
172
+ cached
173
+ cache_creation
174
+ ```
175
+
176
+ A backend may export the subset its telemetry schema supports. The TokenUsage
177
+ value object and each backend's wire representation are separate contracts.
178
+
179
+ ## 11. Backend notes
180
+
181
+ ### NullTracer
182
+
183
+ NullTracer is the default no-op tracer. It avoids external telemetry work but no
184
+ literal "zero runtime cost" guarantee is made.
185
+
186
+ ### Langfuse
187
+
188
+ Langfuse ingestion failure does not fail the Framework automatic logical
189
+ operation. Failures are reported as warnings when possible.
190
+
191
+ ### OpenTelemetry
192
+
193
+ The caller/application configures the OpenTelemetry SDK/exporter. Phronomy does
194
+ not configure an exporter or propagator on the application's behalf.
@@ -0,0 +1,82 @@
1
+ # Phronomy Architecture
2
+
3
+ This is the canonical entry point for Phronomy's **current explanatory
4
+ architecture**.
5
+
6
+ Phronomy deliberately separates architecture intent, implementation reality,
7
+ public contracts, and historical design material:
8
+
9
+ - [Architecture Decision Records](decisions/README.md) are the normative
10
+ decision history and authority for Accepted, non-superseded decisions.
11
+ - The documents linked below explain the reconciled current system.
12
+ - Source/runtime behavior defines current implementation reality.
13
+ - Public APIs and extension SPIs are composite contracts established by runtime
14
+ behavior, `@api` classification, formal API documentation, and explicit
15
+ compatibility/contract tests.
16
+ - RBS represents an already-established contract; it does not create one.
17
+ - Historical and archived designs live under `docs/archive/design/` and are
18
+ non-normative.
19
+
20
+ There is no universal "newest artifact wins" rule. When architecture intent,
21
+ public contract, and implementation reality disagree, the discrepancy must be
22
+ reviewed explicitly rather than resolved by recency.
23
+
24
+ ## Design principles
25
+
26
+ These are design heuristics for new and revised architecture. They do not
27
+ override an Accepted ADR, an established public/extension contract, or an
28
+ explicit compatibility decision.
29
+
30
+ - **Ruby-idiomatic application surface.** Prefer Ruby-idiomatic Application APIs
31
+ and DSLs over mechanical translation of conventions from another language or
32
+ framework.
33
+ - **Progressive adoption.** Keep Phronomy building blocks independently
34
+ adoptable where their semantics allow it. Applications should be able to
35
+ introduce Agent, Tool, Persistence, Workflow, Multi-Agent, and related
36
+ capabilities according to need rather than being forced through the legacy
37
+ Chain/Memory maturity-level model. This does not promise that a subsystem has
38
+ no explicit dependencies required by its own contract.
39
+ - **Small and explicit core dependency surface.** Prefer a small and explicit
40
+ core dependency surface. This is an engineering preference, not a hard invariant:
41
+ dependency minimization must not weaken accepted durability,
42
+ ownership, security-boundary, or extension contracts.
43
+
44
+ ## Current architecture
45
+
46
+ | Area | Current document |
47
+ |---|---|
48
+ | Agent state, identity, ownership, and Context authority | [Agent Context](architecture/agent-context.md) |
49
+ | Per-LLM-call Context Policy and Manifest construction | [Context Management](architecture/context-management.md) |
50
+ | Journal-backed Knowledge and retrieval integration | [Knowledge and RAG](architecture/knowledge-and-rag.md) |
51
+ | Filter, Context trust policy, approval, and isolation boundaries | [Security Boundaries](architecture/security-boundaries.md) |
52
+ | Automatic logical-operation tracing and custom tracer SPI | [Tracing](architecture/tracing.md) |
53
+ | Semantic Source-to-Target responsibility transfer | [Multi-Agent Handoff](architecture/multi-agent-handoff.md) |
54
+ | Durable state, Runtime ownership, recovery, and codec boundaries | [Persistence](architecture/persistence.md) |
55
+ | Request-scoped pre-Manifest customization | [before_llm_input](architecture/before-llm-input.md) |
56
+ | Removed Agent Context / Memory architectures that must not return | [Removed Agent Context Architecture](architecture/removed/agent-context.md) |
57
+
58
+ Runtime execution mechanics are also documented in
59
+ [Runtime and concurrency](runtime-and-concurrency.md), and the custom Persistence
60
+ Backend SPI is documented in
61
+ [Persistence backends](persistence-backends.md).
62
+
63
+ ## Authority and lifecycle
64
+
65
+ Current explanatory architecture documents are maintained to agree with the
66
+ current reconciled repository. They are not substitutes for ADR rationale.
67
+
68
+ Non-current material is split by lifecycle:
69
+
70
+ ```text
71
+ docs/archive/design/historical/
72
+ design snapshots that preserve historical architecture context
73
+
74
+ docs/archive/design/archived/
75
+ obsolete or removed designs retained for historical reference
76
+ ```
77
+
78
+ Archived/historical content may intentionally contain removed APIs and concepts.
79
+ It must not be used as a current implementation or compatibility contract.
80
+
81
+ The old `spec/design/` documentation location is not part of the current
82
+ documentation architecture.