5.4 KiB
5.4 KiB
Decision Service Reference
Overview
DecisionService provides the application-layer interface for recording
decisions during plan execution, retrieving decision histories, and
managing context snapshots. It lives in
src/cleveragents/application/services/decision_service.py.
Dual-Mode Persistence
| Mode | UnitOfWork | Storage |
|---|---|---|
| In-memory | None |
Internal dicts (_decisions, _plan_decisions) |
| Persisted | provided | DB via DecisionRepository + in-memory cache |
When a UnitOfWork is wired, mutations are written to the database
first, then the in-memory cache is updated (write-through).
Constructor
DecisionService(
settings: Settings | None = None,
unit_of_work: UnitOfWork | None = None,
)
- settings – Application settings (optional for in-memory mode).
- unit_of_work – When provided, decisions are persisted via
DecisionRepository.
Recording
record_decision()
svc.record_decision(
plan_id="01HV...",
decision_type=DecisionType.STRATEGY_CHOICE, # or a string
question="Which approach?",
chosen_option="Build a REST API",
parent_decision_id=None, # optional
alternatives_considered=None, # list[str]
confidence_score=None, # 0.0-1.0
rationale="", # human-readable
actor_reasoning=None, # raw LLM trace
context_snapshot=None, # auto-captured if omitted
artifacts_produced=None, # list[ArtifactRef]
is_correction=False,
corrects_decision_id=None,
correction_reason=None,
)
- Auto-assigns a monotonically increasing sequence number per plan.
- Auto-generates a ULID for
decision_id. - Auto-captures a context snapshot (SHA-256 hash) when no explicit snapshot is provided.
- Stores the snapshot in the built-in
SnapshotStore.
Raises:
ValidationError– required fields missing or empty.DuplicateDecisionError– decision ID already exists.
Retrieval
| Method | Description |
|---|---|
get_decision(decision_id) |
Single decision by ULID |
list_decisions(plan_id) |
All decisions for a plan, ordered by seq |
list_by_type(plan_id, decision_type) |
Filtered by type, ordered by seq |
All raise DecisionNotFoundError when the target decision does not
exist (where applicable).
Tree Operations
| Method | Description |
|---|---|
get_tree(plan_id) |
BFS from root(s), level by level |
get_path_to_root(decision_id) |
Walk from a decision up to the root |
Superseded Decisions
| Method | Description |
|---|---|
mark_superseded(decision_id, new_decision_id) |
Mark a decision as superseded |
get_superseded(plan_id) |
List all superseded decisions |
Delete
svc.delete_decision(decision_id) # -> True
Removes from both persistence and the snapshot store. Raises
DecisionNotFoundError if not found.
Snapshot Store
SnapshotStore manages ContextSnapshot objects keyed by decision ID
with hash-based deduplication.
| Method | Description |
|---|---|
get_snapshot(decision_id) |
Retrieve snapshot for a decision |
get_snapshots_for_plan(plan_id) |
All snapshots for a plan's decisions |
snapshots.get_by_hash(hash) |
Decision IDs sharing the same context hash |
snapshots.store(id, snap) |
Store a snapshot (internal) |
snapshots.remove(id) |
Remove a snapshot |
Statistics
| Method | Description |
|---|---|
count_decisions(plan_id) |
Number of decisions for a plan |
get_next_sequence(plan_id) |
Next available sequence number |
Custom Exceptions
| Exception | Base | Description |
|---|---|---|
DuplicateDecisionError |
BusinessRuleViolation |
Decision ID already exists |
DecisionNotFoundError |
ResourceNotFoundError |
Decision not found |
SequenceConflictError |
BusinessRuleViolation |
Sequence number already used |
Running Tests
# Behave BDD tests
nox -s unit_tests -- features/decision_recording.feature
# Robot Framework integration smoke tests
nox -s integration_tests
# ASV benchmarks
nox -s benchmark
Related
- Domain model:
src/cleveragents/domain/models/core/decision.py - Persistence:
src/cleveragents/infrastructure/database/repositories.py(DecisionRepository) - Database schema:
docs/reference/database_schema.md - ADR:
docs/adr/ADR-033-decision-recording-protocol.md