use serde::{Deserialize, Serialize};
pub const CONTEXT_BUNDLE_SCHEMA_VERSION: u32 = 1;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentRole {
Coder,
Reviewer,
Planner,
Researcher,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RiskClass {
Low,
Medium,
High,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DegradedMode {
Full,
CanonicalOnly,
Blocked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SourceKind {
Canonical,
Generated,
GraphDerived,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ItemValidity {
Current,
Stale,
Superseded,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TrustClass {
Trusted,
Standard,
Quarantined,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ContextIntent {
SessionStart,
ResumeWork,
ExplainDecision,
DebugFailure,
ApplyPreference,
ReviewChange,
ExploreHistory,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ChannelKind {
Preferences,
Lessons,
Core,
Workstreams,
MemoryIndex,
Sessions,
}
impl ChannelKind {
pub const ORDERED: [ChannelKind; 6] = [
ChannelKind::Preferences,
ChannelKind::Lessons,
ChannelKind::Core,
ChannelKind::Workstreams,
ChannelKind::MemoryIndex,
ChannelKind::Sessions,
];
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProjectRef {
pub key: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextRequest {
pub schema_version: u32,
pub task: String,
pub project: ProjectRef,
pub branch: Option<String>,
pub worktree: Option<String>,
pub role: AgentRole,
pub as_of_epoch: i64,
pub token_budget: u32,
pub risk: RiskClass,
pub include_superseded: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextItem {
pub stable_key: String,
pub channel: ChannelKind,
pub title: String,
pub text: String,
pub source_kind: SourceKind,
pub canonical_ref: Option<String>,
pub projection_ref: Option<String>,
pub evidence_refs: Vec<String>,
pub validity: ItemValidity,
pub trust: TrustClass,
pub project: Option<String>,
pub branch: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PlannedChannel {
pub channel: ChannelKind,
pub item_limit: u32,
pub relevance_governed: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContextFilters {
pub project: String,
pub branch: Option<String>,
pub include_superseded: bool,
pub as_of_epoch: i64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct SectionBudgets {
pub total_tokens: u32,
pub preferences: u32,
pub lessons: u32,
pub core: u32,
pub workstreams: u32,
pub memory_index: u32,
pub sessions: u32,
}
impl SectionBudgets {
pub fn for_channel(&self, channel: ChannelKind) -> u32 {
match channel {
ChannelKind::Preferences => self.preferences,
ChannelKind::Lessons => self.lessons,
ChannelKind::Core => self.core,
ChannelKind::Workstreams => self.workstreams,
ChannelKind::MemoryIndex => self.memory_index,
ChannelKind::Sessions => self.sessions,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AuditEntry {
pub stable_key: String,
pub channel: ChannelKind,
pub source_kind: SourceKind,
pub validity: ItemValidity,
pub selected: bool,
pub reason: String,
pub relevance_score: Option<f64>,
pub token_estimate: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextAudit {
pub schema_version: u32,
pub policy_version: String,
pub relevance_policy_version: String,
pub plan_hash: String,
pub degraded_mode: DegradedMode,
pub candidates_considered: u32,
pub selected_count: u32,
pub dropped_count: u32,
pub token_estimate: u32,
pub token_budget: u32,
pub truncation_reason: Option<String>,
pub entries: Vec<AuditEntry>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextBundle {
pub schema_version: u32,
pub plan_hash: String,
pub degraded_mode: DegradedMode,
pub preferences: Vec<ContextItem>,
pub failure_lessons: Vec<ContextItem>,
pub current_truth: Vec<ContextItem>,
pub workstreams: Vec<ContextItem>,
pub memory_index: Vec<ContextItem>,
pub recent_sessions: Vec<ContextItem>,
pub audit: ContextAudit,
}
impl ContextBundle {
pub fn section_mut(&mut self, channel: ChannelKind) -> &mut Vec<ContextItem> {
match channel {
ChannelKind::Preferences => &mut self.preferences,
ChannelKind::Lessons => &mut self.failure_lessons,
ChannelKind::Core => &mut self.current_truth,
ChannelKind::Workstreams => &mut self.workstreams,
ChannelKind::MemoryIndex => &mut self.memory_index,
ChannelKind::Sessions => &mut self.recent_sessions,
}
}
}