120274da99
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 20s
CI / quality (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 33s
CI / security (pull_request) Successful in 35s
CI / integration_tests (pull_request) Successful in 4m26s
CI / unit_tests (pull_request) Successful in 20m49s
CI / benchmark-regression (pull_request) Successful in 20m19s
CI / docker (pull_request) Successful in 1m2s
CI / coverage (pull_request) Successful in 48m2s
CI / lint (push) Successful in 12s
CI / quality (push) Successful in 16s
CI / build (push) Successful in 24s
CI / typecheck (push) Successful in 29s
CI / security (push) Successful in 30s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m44s
CI / unit_tests (push) Successful in 11m56s
CI / benchmark-publish (push) Successful in 12m13s
CI / docker (push) Successful in 39s
CI / coverage (push) Successful in 37m29s
Create DecisionService application-layer service that wraps DecisionRepository with structured logging and UnitOfWork transaction management. Wire DecisionService and PlanLifecycleService into the DI container as Factory providers. Inject DecisionService into PlanLifecycleService so that phase transitions automatically record decisions: start_strategize records a strategy_choice decision and start_execute records an implementation_choice decision. Decision recording is optional and never blocks lifecycle transitions. Add Behave feature (5 scenarios), Robot Framework smoke tests (2 test cases), ASV benchmarks (3 benchmark classes), and DI reference documentation. ISSUES CLOSED: #173
4.4 KiB
4.4 KiB
Dependency Injection Reference
The CleverAgents DI container is built on dependency-injector's
DeclarativeContainer. All service registrations live in
src/cleveragents/application/container.py.
Container Overview
| Provider | Type | Description |
|---|---|---|
settings |
Singleton | Application settings |
provider_registry |
Singleton | AI provider registry |
database_url |
Callable | Database URL resolution |
unit_of_work |
Factory | Unit of Work (new per request) |
ai_provider |
Singleton | AI provider instance |
project_service |
Factory | Project management service |
vector_store_service |
Factory | Vector store operations |
context_service |
Factory | Context management service |
actor_service |
Factory | Actor configuration service |
actor_registry |
Factory | Actor registry with provider binding |
plan_service |
Factory | Legacy plan management (deprecated) |
decision_service |
Factory | Decision tree recording service |
plan_lifecycle_service |
Factory | V3 four-phase plan lifecycle |
resource_registry_service |
Factory | Resource registry operations |
namespaced_project_repo |
Factory | Namespaced project repository |
project_resource_link_repo |
Factory | Project-resource link repository |
stream_router |
Singleton | Reactive stream routing |
langgraph_bridge |
Singleton | LangGraph integration bridge |
route_bridge |
Singleton | Reactive route bridge |
Decision Service Registration
The DecisionService is registered as a Factory provider, meaning
each resolution returns a new instance. It depends on:
settings— Application settings (Singleton)unit_of_work— Unit of Work (Factory)
decision_service = providers.Factory(
DecisionService,
settings=settings,
unit_of_work=unit_of_work,
)
DecisionService wraps DecisionRepository (accessible via
UnitOfWorkContext.decisions) and provides:
| Method | Description |
|---|---|
record_decision() |
Persist a new decision |
get_decision() |
Retrieve a decision by ID |
get_decisions_for_plan() |
Get all decisions for a plan |
get_decision_tree() |
BFS traversal of the decision tree |
get_path_to_root() |
Walk from a decision up to the root |
mark_superseded() |
Mark a decision as superseded |
list_by_type() |
List decisions by type for a plan |
Plan Lifecycle Service Registration
The PlanLifecycleService is registered as a Factory provider
with the DecisionService injected:
plan_lifecycle_service = providers.Factory(
PlanLifecycleService,
settings=settings,
unit_of_work=unit_of_work,
decision_service=decision_service,
)
When a DecisionService is wired, the lifecycle service automatically
records decisions during phase transitions:
- start_strategize → records a
strategy_choicedecision - start_execute → records an
implementation_choicedecision
If no DecisionService is provided (e.g. in legacy tests), decision
recording is silently skipped.
Usage Example
from cleveragents.application.container import get_container
container = get_container()
# Resolve services
decision_svc = container.decision_service()
lifecycle_svc = container.plan_lifecycle_service()
# Record a decision manually
from cleveragents.domain.models.core.decision import Decision, DecisionType
decision = Decision(
plan_id="01HV...",
sequence_number=0,
decision_type=DecisionType.STRATEGY_CHOICE,
question="Which approach?",
chosen_option="Approach A",
)
decision_svc.record_decision(decision)
# Retrieve decisions
decisions = decision_svc.get_decisions_for_plan("01HV...")