Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Refactored the engine's internal runtime composition into an immutable component snapshot; zero public API change and no execution-semantic changes, except the intentional fail-fast rejection of invalid partial approval composition at the engine component boundary.

- **Explicit runtime lifecycle ownership (PR #226).** `Tramai` and `SovereignTramai` are now `AutoCloseable` and own exactly one lazily-created runtime (one engine) shared by every `create()`/`runtime()` call — previously every `create()` leaked an unreachable engine. Closing is idempotent and concurrency-safe; after close, `create()`/`runtime()` and old proxies fail fast with a fixed `IllegalStateException` before any provider work. `TramaiEngine.close()` cancels once and awaits engine-hierarchy termination (self-close safe), and terminates in-flight suspend invocations; the caller continuation is always resumed exactly once. Spring closes the shared runtime via `destroyMethod = "close"`, so multiple `@AiService` beans share one owned engine. TramAI closes only resources it creates; externally supplied providers/stores/clients/observers remain caller-owned. API surface addition is additive: `Tramai`/`SovereignTramai` gain `close()`; all constructor descriptors remain byte-identical to 0.5.0 (note: adding the `AutoCloseable` supertype is source-compatible but affects compiled negative-`instanceof` checks). Epic 1.3 Runtime Lifecycle Ownership is complete.

- **Safe persistence failure boundaries (PR #225).** Persistence stores expose fixed, cause-free failure text; raw paths, SQL, and payloads flow only to `PersistenceFailureDiagnosticObserver`; worker observers receive safe failures; existing exception and store ABI is preserved by the binary fixture. Epic 1.2 Safe Error Boundaries is complete.
Expand Down
10 changes: 10 additions & 0 deletions config/quality/maintainability-deviations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ deviations:
targetPhase: "0.6.1"
owner: "GionaGranchelli"

- id: MQ-0017
metric: globalMutableState
scope: ":tramai-engine"
baseline: 18
allowed: 22
reason: "Epic 2.1 EngineComponents snapshot: internal data-class fields typed as ProviderRegistry/ToolRegistry/ModelRegistry are immutable final snapshot references, not mutable registries. Scanner counts them as exposed registry state; they are the frozen configuration boundary (EngineComponentFactory is the sole construction path). Findings resolve when the scanner learns to distinguish snapshot references."
acceptedAt: "2026-08-12"
targetPhase: "0.6.1"
owner: "GionaGranchelli"

- id: MQ-0015
metric: nondeterminismSources
scope: ":tramai-orchestration"
Expand Down
20 changes: 11 additions & 9 deletions docs/ROADMAP-0.6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ This phase is intentionally completed before large decomposition work.

## Epic 2.1: Introduce immutable runtime component groups

**Status: ✅ Complete — PR #228**

**Goal:** Replace constructor and builder explosion with cohesive, inspectable runtime configuration.

### Proposed component model
Expand All @@ -441,18 +443,18 @@ The exact API may differ, but each group must have one responsibility and explic

### Tasks

1. Introduce immutable component groups without changing public builder APIs initially.
2. Move all all-or-none composition validation into component constructors or factories.
3. Distinguish required components, optional capabilities, and no-op implementations.
4. Replace nullable dependency clusters with explicit capability types where possible.
5. Document thread-safety and lifecycle ownership for every component group.
6. Ensure component snapshots are immutable after runtime construction.
1. Introduce immutable component groups without changing public builder APIs initially.
2. Move all all-or-none composition validation into component constructors or factories.
3. Distinguish required components, optional capabilities, and no-op implementations.
4. Replace nullable dependency clusters with explicit capability types where possible.
5. Document thread-safety and lifecycle ownership for every component group.
6. Ensure component snapshots are immutable after runtime construction.

### Acceptance criteria

- `TramaiEngine` and its main execution coordinators receive cohesive component groups rather than dozens of unrelated dependencies.
- Invalid partial approval, policy, persistence, or evidence configurations fail during build.
- Runtime code does not discover configuration dynamically.
- `TramaiEngine` and its main execution coordinators receive cohesive component groups rather than dozens of unrelated dependencies.
- Invalid partial approval, policy, persistence, or evidence configurations fail during build.
- Runtime code does not discover configuration dynamically.

---

Expand Down
1 change: 1 addition & 0 deletions docs/modules/tramai-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ implementation("dev.tramai:tramai-engine")
### Quick usage

The most common pattern: create a `TramaiEngine` with a single provider, then call `engine.create<T>()` to obtain a proxy.
Public construction remains unchanged. Internally, each construction call validates and freezes an immutable component snapshot before runtime use.

```kotlin
import dev.tramai.engine.TramaiEngine
Expand Down
Loading
Loading