do_memory_core/context/mod.rs
1//! Bounded context assembly for retrieval results.
2//!
3//! This module provides `BundleAccumulator`, a sliding window accumulator that
4//! bounds retrieval context size by recency and salience instead of flat accumulation.
5//!
6//! ## Purpose
7//!
8//! When retrieving episodes and patterns for downstream prompts (e.g., LLM context),
9//! flat accumulation can result in:
10//! - Excessive token usage (too many items)
11//! - Irrelevant items (low-quality matches included)
12//! - Stale context (old items dominating recent ones)
13//!
14//! `BundleAccumulator` addresses these by:
15//! - Capping the number of items via a sliding window
16//! - Prioritizing by combined recency + salience scoring
17//! - Evicting lowest-priority items when capacity exceeded
18//!
19//! ## Architecture
20//!
21//! ```text
22//! Retrieval Results
23//! |
24//! v
25//! ContextItem (Episode/Pattern + Salience)
26//! |
27//! v
28//! BundleAccumulator (Sliding Window)
29//! | - Check salience threshold
30//! | - Compute priority = recency_weight * recency + salience_weight * salience
31//! | - Evict lowest priority if full
32//! v
33//! Bounded Bundle (sorted by priority)
34//! |
35//! v
36//! Downstream Prompt
37//! ```
38//!
39//! ## Quick Start
40//!
41//! ```
42//! use do_memory_core::context::{BundleAccumulator, BundleConfig, ContextItem};
43//! use do_memory_core::episode::Episode;
44//! use do_memory_core::TaskContext;
45//! use do_memory_core::types::TaskType;
46//! use std::sync::Arc;
47//!
48//! // Create accumulator with default config (20 items max)
49//! let mut accumulator = BundleAccumulator::default_config();
50//!
51//! // Add retrieved episodes with their salience scores
52//! let episode = Episode::new(
53//! "Fix authentication bug".to_string(),
54//! TaskContext::default(),
55//! TaskType::Debugging,
56//! );
57//! let item = ContextItem::from_episode(Arc::new(episode), 0.85);
58//! accumulator.add(item);
59//!
60//! // Finalize bundle for prompt
61//! let bundle = accumulator.to_bundle();
62//! println!("Bundle contains {} items for prompt", bundle.len());
63//! ```
64//!
65//! ## Configuration Options
66//!
67//! ```
68//! use do_memory_core::context::BundleConfig;
69//!
70//! // Token-efficient: smaller bundle, higher quality threshold
71//! let token_config = BundleConfig::token_efficient();
72//!
73//! // Comprehensive: larger bundle, lower threshold
74//! let full_config = BundleConfig::comprehensive();
75//!
76//! // Custom: tune for specific needs
77//! let custom = BundleConfig {
78//! max_items: 15, // Allow 15 items
79//! recency_weight: 0.6, // Favor recent items
80//! salience_weight: 0.3, // Still consider retrieval score
81//! min_salience_threshold: 0.3, // Reject very low salience
82//! recency_half_life_days: 14.0, // Recent = last 2 weeks
83//! };
84//! ```
85//!
86//! ## Integration with Retrieval
87//!
88//! The accumulator is designed to sit between retrieval results and prompt construction:
89//!
90//! ```no_run
91//! use do_memory_core::memory::SelfLearningMemory;
92//! use do_memory_core::context::{BundleAccumulator, BundleConfig};
93//! use do_memory_core::TaskContext;
94//!
95//! # async fn example(memory: SelfLearningMemory) {
96//! // Retrieve episodes (unbounded)
97//! let episodes = memory.retrieve_relevant_context(
98//! "Implement OAuth2".to_string(),
99//! TaskContext::default(),
100//! 50, // May retrieve up to 50
101//! ).await;
102//!
103//! // Create bounded bundle
104//! let bundle = BundleAccumulator::from_episodes_with_config(
105//! episodes,
106//! BundleConfig::token_efficient(),
107//! |ep| ep.reward.as_ref().map_or(0.5, |r| r.total),
108//! );
109//!
110//! // bundle.len() <= 10 (bounded for token efficiency)
111//! # }
112//! ```
113//!
114//! ## Modules
115//!
116//! - [`types`]: Core types (`ContextItem`, `BundleConfig`, `BundleStats`)
117//! - [`accumulator`]: `BundleAccumulator` implementation
118//! - [`scoring`]: Priority and recency scoring functions
119
120pub mod accumulator;
121pub mod scoring;
122pub mod types;
123
124#[cfg(test)]
125mod tests;
126
127#[cfg(test)]
128mod tests_edge;
129
130// Re-export public types
131pub use accumulator::BundleAccumulator;
132pub use scoring::{
133 calculate_priority_score, calculate_recency_score, compare_by_priority, compare_by_recency,
134 compare_by_salience,
135};
136pub use types::{AddResult, BundleConfig, BundleStats, ContextItem, ContextItemType};