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//! ## DAG-Based State Management (WG-134)
20//!
21//! The `dag` submodule provides DAG-based state management achieving ~86% token
22//! reduction by deduplicating shared context between episodes:
23//! - `StateDag`: Manages shared context nodes
24//! - `DagContextAssembler`: Assembles minimal deduplicated context
25//!
26//! ## Architecture
27//!
28//! ```text
29//! Retrieval Results
30//! |
31//! v
32//! ContextItem (Episode/Pattern + Salience)
33//! |
34//! v
35//! BundleAccumulator (Sliding Window)
36//! | - Check salience threshold
37//! | - Compute priority = recency_weight * recency + salience_weight * salience
38//! | - Evict lowest priority if full
39//! v
40//! Bounded Bundle (sorted by priority)
41//! |
42//! v
43//! DagContextAssembler (WG-134)
44//! | - Deduplicate shared context
45//! | - ~86% token reduction
46//! v
47//! Downstream Prompt
48//! ```
49//!
50//! ## Quick Start
51//!
52//! ```
53//! use do_memory_core::context::{BundleAccumulator, BundleConfig, ContextItem};
54//! use do_memory_core::episode::Episode;
55//! use do_memory_core::TaskContext;
56//! use do_memory_core::types::TaskType;
57//! use std::sync::Arc;
58//!
59//! // Create accumulator with default config (20 items max)
60//! let mut accumulator = BundleAccumulator::default_config();
61//!
62//! // Add retrieved episodes with their salience scores
63//! let episode = Episode::new(
64//! "Fix authentication bug".to_string(),
65//! TaskContext::default(),
66//! TaskType::Debugging,
67//! );
68//! let item = ContextItem::from_episode(Arc::new(episode), 0.85);
69//! accumulator.add(item);
70//!
71//! // Finalize bundle for prompt
72//! let bundle = accumulator.to_bundle();
73//! println!("Bundle contains {} items for prompt", bundle.len());
74//! ```
75//!
76//! ## Configuration Options
77//!
78//! ```
79//! use do_memory_core::context::BundleConfig;
80//!
81//! // Token-efficient: smaller bundle, higher quality threshold
82//! let token_config = BundleConfig::token_efficient();
83//!
84//! // Comprehensive: larger bundle, lower threshold
85//! let full_config = BundleConfig::comprehensive();
86//!
87//! // Custom: tune for specific needs
88//! let custom = BundleConfig {
89//! max_items: 15, // Allow 15 items
90//! recency_weight: 0.6, // Favor recent items
91//! salience_weight: 0.3, // Still consider retrieval score
92//! min_salience_threshold: 0.3, // Reject very low salience
93//! recency_half_life_days: 14.0, // Recent = last 2 weeks
94//! };
95//! ```
96//!
97//! ## Integration with Retrieval
98//!
99//! The accumulator is designed to sit between retrieval results and prompt construction:
100//!
101//! ```no_run
102//! use do_memory_core::memory::SelfLearningMemory;
103//! use do_memory_core::context::{BundleAccumulator, BundleConfig};
104//! use do_memory_core::TaskContext;
105//!
106//! # async fn example(memory: SelfLearningMemory) {
107//! // Retrieve episodes (unbounded)
108//! let episodes = memory.retrieve_relevant_context(
109//! "Implement OAuth2".to_string(),
110//! TaskContext::default(),
111//! 50, // May retrieve up to 50
112//! ).await;
113//!
114//! // Create bounded bundle
115//! let bundle = BundleAccumulator::from_episodes_with_config(
116//! episodes,
117//! BundleConfig::token_efficient(),
118//! |ep| ep.reward.as_ref().map_or(0.5, |r| r.total),
119//! );
120//!
121//! // bundle.len() <= 10 (bounded for token efficiency)
122//! # }
123//! ```
124//!
125//! ## Modules
126//!
127//! - [`types`]: Core types (`ContextItem`, `BundleConfig`, `BundleStats`)
128//! - [`accumulator`]: `BundleAccumulator` implementation
129//! - [`scoring`]: Priority and recency scoring functions
130//! - [`dag`]: DAG-based state management (WG-134, ~86% token reduction)
131
132pub mod accumulator;
133pub mod dag;
134pub mod scoring;
135pub mod types;
136
137#[cfg(test)]
138mod tests;
139
140#[cfg(test)]
141mod tests_edge;
142
143// Re-export public types
144pub use accumulator::BundleAccumulator;
145pub use scoring::{
146 calculate_priority_score, calculate_recency_score, compare_by_priority, compare_by_recency,
147 compare_by_salience,
148};
149pub use types::{AddResult, BundleConfig, BundleStats, ContextItem, ContextItemType};
150
151// Re-export DAG types (WG-134)
152pub use dag::{
153 AssembledContext, DagAssemblyConfig, DagContextAssembler, DagStats, EdgeMetadata, EdgeType,
154 NodeId, StateDag, StateEdge, StateNode, StateNodeType,
155};