use std::collections::{BTreeMap, HashSet};
use std::path::Path;
use crate::db;
use crate::paths::state::StateLayout;
use crate::state::runtime as runtime_state;
use crate::state::session as session_state;
use crate::timestamps;
use anyhow::Result;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
const SCHEMA_VERSION: u32 = 6;
const DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE: usize = 12;
const DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION: usize = 8;
pub(crate) const SESSION_RENDER_SURFACE_ORDER: &[&str] = &[
"effective_memory",
"handoff",
"execution_gates",
"escalation",
"recovery",
"git_state",
"session_state",
];
const TOOL_SURFACE_FINGERPRINT_VARS: &[&str] = &[
"CCD_TOOL_SURFACE_FINGERPRINT",
"CCD_MCP_TOOL_SURFACE_FINGERPRINT",
];
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct ProjectionDigests {
pub effective_memory: String,
pub handoff: String,
#[serde(default)]
pub execution_gates: String,
#[serde(default)]
pub escalation: String,
#[serde(default)]
pub recovery: String,
#[serde(default)]
pub git_state: String,
#[serde(default)]
pub session_state: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompiledStateStore {
pub schema_version: u32,
#[serde(default = "default_projection_target")]
pub target: ProjectionTarget,
pub source_fingerprint: String,
#[serde(default)]
pub pod_identity_active: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub projection_digests: Option<ProjectionDigests>,
pub effective_memory: CompiledMemoryView,
pub handoff: CompiledHandoffView,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompiledMemoryView {
pub profile: Vec<String>,
#[serde(alias = "repo")]
pub locality: Vec<String>,
#[serde(default)]
pub pod: Vec<String>,
#[serde(default)]
pub branch: Vec<String>,
#[serde(default)]
pub clone: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompiledHandoffView {
pub title: String,
pub immediate_actions: Vec<String>,
pub completed_state: Vec<String>,
pub operational_guardrails: Vec<String>,
pub key_files: Vec<String>,
pub definition_of_done: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct CompiledStateSurfaceView {
pub path: String,
pub status: &'static str,
pub schema_version: u32,
pub target: &'static str,
pub source_fingerprint: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_reason: Option<&'static str>,
}
pub struct PreparedCompiledState {
pub surface: CompiledStateSurfaceView,
pub store: CompiledStateStore,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct ProjectionDeltaStats {
pub skipped: u32,
pub refreshed: u32,
pub total: u32,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct ProjectionTokenTelemetry {
pub surface_tokens: BTreeMap<String, u64>,
pub format_tokens: BTreeMap<String, u64>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ProjectionResolution<T> {
pub value: T,
pub cadence: ProjectionFormatCadenceCurrent,
}
#[derive(Debug, Clone, Serialize)]
pub struct ProjectionFormatCadenceCurrent {
pub target: &'static str,
pub format: &'static str,
pub cache_status: &'static str,
pub observed_at_epoch_s: u64,
pub source_fingerprint: String,
#[serde(skip_serializing_if = "String::is_empty")]
pub tool_surface_fingerprint: String,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct ProjectionFormatCadenceSummary {
pub event_count: u32,
pub hit_count: u32,
pub miss_count: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub hit_ratio: Option<f64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProjectionFormat {
Narrative,
Symbolic,
Bundle,
}
impl ProjectionFormat {
pub fn as_str(self) -> &'static str {
match self {
Self::Narrative => "narrative",
Self::Symbolic => "symbolic",
Self::Bundle => "bundle",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProjectionTarget {
Default,
Planning,
Session,
}
impl ProjectionTarget {
pub fn as_str(self) -> &'static str {
match self {
Self::Default => "default",
Self::Planning => "planning",
Self::Session => "session",
}
}
}
fn persisted_target() -> ProjectionTarget {
ProjectionTarget::Session
}
fn default_projection_target() -> ProjectionTarget {
ProjectionTarget::Default
}
#[derive(Debug, Clone, Copy)]
struct ProjectionBounds {
max_active_memory_entries_per_scope: usize,
max_active_handoff_items_per_section: usize,
}
#[cfg_attr(not(test), allow(dead_code))]
pub fn ensure_for_runtime(
layout: &StateLayout,
loaded: &runtime_state::LoadedRuntimeState,
) -> Result<PreparedCompiledState> {
let compiled = preview_for_target_with_cache(layout, loaded, persisted_target())?.value;
Ok(PreparedCompiledState {
surface: computed_surface_view(layout, &compiled),
store: compiled,
})
}
pub fn refresh_after_write(
repo_root: &Path,
layout: &StateLayout,
locality_id: &str,
) -> Result<CompiledStateStore> {
compile_from_runtime_for_target(repo_root, layout, locality_id, persisted_target())
}
pub fn refresh_after_write_with_loaded(
layout: &StateLayout,
loaded: &runtime_state::LoadedRuntimeState,
) -> Result<CompiledStateStore> {
preview_for_target_with_cache(layout, loaded, persisted_target())
.map(|resolution| resolution.value)
}
pub struct StartCompiledResult {
pub compiled: PreparedCompiledState,
pub sources: runtime_state::RuntimeSourceSurfaces,
pub recovery: runtime_state::LoadedRuntimeRecoveryState,
}
fn computed_surface_view(
layout: &StateLayout,
store: &CompiledStateStore,
) -> CompiledStateSurfaceView {
CompiledStateSurfaceView {
path: layout.state_db_path().display().to_string(),
status: "computed",
schema_version: store.schema_version,
target: store.target.as_str(),
source_fingerprint: store.source_fingerprint.clone(),
refresh_reason: None,
}
}
pub fn ensure_for_start(
layout: &StateLayout,
raw: runtime_state::RawRuntimeSources,
) -> Result<StartCompiledResult> {
let loaded = runtime_state::normalize_raw_into_loaded(raw)?;
let compiled = preview_for_target_with_cache(layout, &loaded, persisted_target())?.value;
Ok(StartCompiledResult {
compiled: PreparedCompiledState {
surface: computed_surface_view(layout, &compiled),
store: compiled,
},
sources: loaded.sources,
recovery: loaded.recovery,
})
}
pub fn compute_projection_digests(store: &CompiledStateStore) -> ProjectionDigests {
ProjectionDigests {
effective_memory: sha256_string(&render_memory_content(
&store.effective_memory,
store.pod_identity_active,
)),
handoff: sha256_string(&render_handoff_content(&store.handoff)),
execution_gates: String::new(),
escalation: String::new(),
recovery: String::new(),
git_state: String::new(),
session_state: String::new(),
}
}
pub fn compute_extended_digests(
base: &ProjectionDigests,
execution_gates_json: &str,
escalation_json: &str,
recovery_json: &str,
git_state_json: &str,
session_state_json: &str,
) -> ProjectionDigests {
ProjectionDigests {
effective_memory: base.effective_memory.clone(),
handoff: base.handoff.clone(),
execution_gates: sha256_string(execution_gates_json),
escalation: sha256_string(escalation_json),
recovery: sha256_string(recovery_json),
git_state: sha256_string(git_state_json),
session_state: sha256_string(session_state_json),
}
}
pub(crate) fn current_tool_surface_fingerprint() -> String {
db::projection_cache::normalize_tool_surface_fingerprint(
TOOL_SURFACE_FINGERPRINT_VARS
.iter()
.find_map(|name| {
std::env::var(name)
.ok()
.map(|value| value.trim().to_owned())
.filter(|value| !value.is_empty())
})
.as_deref(),
)
}
pub(crate) fn estimate_tokens(chars: usize) -> u64 {
u64::try_from(chars.div_ceil(4)).unwrap_or(u64::MAX)
}
pub fn render_narrative_projection_content(store: &CompiledStateStore) -> String {
let mut sections = Vec::new();
let effective_memory =
render_memory_content(&store.effective_memory, store.pod_identity_active);
if !effective_memory.is_empty() {
sections.push(("Effective Memory", effective_memory));
}
let handoff = render_handoff_content(&store.handoff);
if !handoff.is_empty() {
sections.push(("Handoff", handoff));
}
sections
.into_iter()
.map(|(title, body)| format!("{title}\n{body}"))
.collect::<Vec<_>>()
.join("\n\n")
}
pub fn compute_projection_delta_stats(
previous: &ProjectionDigests,
current: &ProjectionDigests,
) -> ProjectionDeltaStats {
let pairs: &[(&str, &str)] = &[
(&previous.effective_memory, ¤t.effective_memory),
(&previous.handoff, ¤t.handoff),
(&previous.execution_gates, ¤t.execution_gates),
(&previous.escalation, ¤t.escalation),
(&previous.recovery, ¤t.recovery),
(&previous.git_state, ¤t.git_state),
(&previous.session_state, ¤t.session_state),
];
let mut stats = ProjectionDeltaStats {
skipped: 0,
refreshed: 0,
total: pairs.len() as u32,
};
for (previous_digest, current_digest) in pairs {
if !previous_digest.is_empty() && previous_digest == current_digest {
stats.skipped = stats.skipped.saturating_add(1);
} else {
stats.refreshed = stats.refreshed.saturating_add(1);
}
}
stats
}
pub fn compute_surface_token_counts(
store: &CompiledStateStore,
execution_gates_json: &str,
escalation_json: &str,
recovery_json: &str,
git_state_json: &str,
session_state_json: &str,
) -> BTreeMap<String, u64> {
let mut counts = BTreeMap::new();
counts.insert(
"effective_memory".to_owned(),
estimate_tokens(
render_memory_content(&store.effective_memory, store.pod_identity_active)
.chars()
.count(),
),
);
counts.insert(
"handoff".to_owned(),
estimate_tokens(render_handoff_content(&store.handoff).chars().count()),
);
counts.insert(
"execution_gates".to_owned(),
estimate_tokens(execution_gates_json.chars().count()),
);
counts.insert(
"escalation".to_owned(),
estimate_tokens(escalation_json.chars().count()),
);
counts.insert(
"recovery".to_owned(),
estimate_tokens(recovery_json.chars().count()),
);
counts.insert(
"git_state".to_owned(),
estimate_tokens(git_state_json.chars().count()),
);
counts.insert(
"session_state".to_owned(),
estimate_tokens(session_state_json.chars().count()),
);
counts
}
pub fn compute_format_token_counts(
narrative: &CompiledStateStore,
symbolic: &SymbolicProjectionView,
bundle: &BundleProjectionView,
) -> BTreeMap<String, u64> {
let mut counts = BTreeMap::new();
counts.insert(
ProjectionFormat::Narrative.as_str().to_owned(),
estimate_tokens(
render_narrative_projection_content(narrative)
.chars()
.count(),
),
);
counts.insert(
ProjectionFormat::Symbolic.as_str().to_owned(),
estimate_tokens(render_symbolic_content(symbolic).chars().count()),
);
counts.insert(
ProjectionFormat::Bundle.as_str().to_owned(),
estimate_tokens(bundle.markdown.chars().count()),
);
counts
}
pub fn cadence_summary_for_target(
layout: &StateLayout,
target: ProjectionTarget,
limit: usize,
) -> Result<BTreeMap<String, ProjectionFormatCadenceSummary>> {
if !layout.state_db_path().exists() {
return Ok(default_cadence_summary_map());
}
let db = db::StateDb::open(&layout.state_db_path())?;
let events =
db::projection_cache::list_recent_events_for_target(db.conn(), target.as_str(), limit)?;
let mut summaries = default_cadence_summary_map();
for event in events {
let entry = summaries.entry(event.format).or_default();
entry.event_count = entry.event_count.saturating_add(1);
if event.cache_status == "hit" {
entry.hit_count = entry.hit_count.saturating_add(1);
} else {
entry.miss_count = entry.miss_count.saturating_add(1);
}
}
for summary in summaries.values_mut() {
if summary.event_count > 0 {
summary.hit_ratio = Some(round_ratio(
(summary.hit_count as f64) / (summary.event_count as f64),
));
}
}
Ok(summaries)
}
fn default_cadence_summary_map() -> BTreeMap<String, ProjectionFormatCadenceSummary> {
let mut summaries = BTreeMap::new();
for format in [
ProjectionFormat::Narrative,
ProjectionFormat::Symbolic,
ProjectionFormat::Bundle,
] {
summaries.insert(
format.as_str().to_owned(),
ProjectionFormatCadenceSummary::default(),
);
}
summaries
}
fn round_ratio(value: f64) -> f64 {
(value * 1000.0).round() / 1000.0
}
pub(crate) fn sha256_string(content: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(content.as_bytes());
format!("{:x}", hasher.finalize())
}
pub fn render_memory_content(view: &CompiledMemoryView, pod_identity_active: bool) -> String {
let mut body = String::new();
if pod_identity_active {
append_section(&mut body, "Pod Memory", &view.pod);
append_section(&mut body, "Profile Memory", &view.profile);
append_section(&mut body, "Project Memory", &view.locality);
} else {
append_section(&mut body, "Profile Memory", &view.profile);
append_section(&mut body, "Project Memory", &view.locality);
append_section(&mut body, "Pod Memory", &view.pod);
}
append_section(&mut body, "Work Stream Memory", &view.branch);
append_section(&mut body, "Workspace Memory", &view.clone);
body
}
pub fn render_handoff_content(view: &CompiledHandoffView) -> String {
let mut body = String::new();
if !view.title.is_empty() {
append_section(&mut body, "Title", std::slice::from_ref(&view.title));
}
append_section(&mut body, "Immediate Actions", &view.immediate_actions);
append_section(&mut body, "Completed State", &view.completed_state);
append_section(
&mut body,
"Operational Guardrails",
&view.operational_guardrails,
);
append_section(&mut body, "Key Files", &view.key_files);
append_section(&mut body, "Definition of Done", &view.definition_of_done);
body
}
#[derive(Debug, Clone, Serialize)]
pub struct ContextDelta {
pub previous_fingerprint: String,
pub current_fingerprint: String,
pub changed_surfaces: Vec<ChangedSurface>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ChangedSurface {
pub name: &'static str,
pub previous_digest: String,
pub current_digest: String,
}
fn surface_name_to_static(name: &str) -> &'static str {
match name {
"effective_memory" => "effective_memory",
"handoff" => "handoff",
"execution_gates" => "execution_gates",
"escalation" => "escalation",
"recovery" => "recovery",
"git_state" => "git_state",
"session_state" => "session_state",
_ => "unknown",
}
}
#[cfg_attr(not(test), allow(dead_code))]
pub fn compute_context_delta(
previous: &ProjectionDigests,
current: &ProjectionDigests,
previous_fp: &str,
current_fp: &str,
) -> Option<ContextDelta> {
let pairs: &[(&str, &str, &str)] = &[
(
"effective_memory",
&previous.effective_memory,
¤t.effective_memory,
),
("handoff", &previous.handoff, ¤t.handoff),
(
"execution_gates",
&previous.execution_gates,
¤t.execution_gates,
),
("escalation", &previous.escalation, ¤t.escalation),
("recovery", &previous.recovery, ¤t.recovery),
("git_state", &previous.git_state, ¤t.git_state),
(
"session_state",
&previous.session_state,
¤t.session_state,
),
];
let mut changed = Vec::new();
for &(name, prev, curr) in pairs {
if prev.is_empty() || curr.is_empty() {
continue;
}
if prev != curr {
changed.push(ChangedSurface {
name: surface_name_to_static(name),
previous_digest: prev.to_owned(),
current_digest: curr.to_owned(),
});
}
}
if changed.is_empty() {
return None;
}
Some(ContextDelta {
previous_fingerprint: previous_fp.to_owned(),
current_fingerprint: current_fp.to_owned(),
changed_surfaces: changed,
})
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolicProjectionView {
pub target: ProjectionTarget,
pub source_fingerprint: String,
pub facts: Vec<SymbolicFact>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BundleProjectionView {
pub target: ProjectionTarget,
pub source_fingerprint: String,
pub task: String,
pub sections: Vec<BundleSection>,
pub markdown: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct BundleSection {
pub kind: BundleSectionKind,
pub title: String,
pub items: Vec<String>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum BundleSectionKind {
Do,
Remember,
Focus,
Rules,
Files,
CloseOut,
State,
}
impl BundleSectionKind {
fn title(self) -> &'static str {
match self {
Self::Do => "Do",
Self::Remember => "Remember",
Self::Focus => "Focus",
Self::Rules => "Rules",
Self::Files => "Files",
Self::CloseOut => "Close-out",
Self::State => "State",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SymbolicFact {
pub surface: String,
pub kind: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub ordinal: Option<usize>,
pub text: String,
}
#[cfg_attr(not(test), allow(dead_code))]
pub fn render_symbolic_content(view: &SymbolicProjectionView) -> String {
view.facts
.iter()
.map(render_symbolic_fact)
.collect::<Vec<_>>()
.join("\n")
}
pub fn preview_for_target(
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<CompiledStateStore> {
compile_loaded_runtime_for_target(loaded, target)
}
pub fn preview_for_target_with_cache(
layout: &StateLayout,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<ProjectionResolution<CompiledStateStore>> {
let source_fingerprint = fingerprint_for_inputs(&loaded.sources, loaded.pod_identity_active)?;
preview_with_precomputed_fingerprint(layout, None, loaded, target, &source_fingerprint, true)
}
pub(crate) fn preview_with_precomputed_fingerprint(
layout: &StateLayout,
shared_db: Option<&db::StateDb>,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
source_fingerprint: &str,
record_event: bool,
) -> Result<ProjectionResolution<CompiledStateStore>> {
resolve_cached_projection(
layout,
shared_db,
target,
ProjectionFormat::Narrative,
source_fingerprint,
record_event,
|| compile_loaded_runtime_for_target(loaded, target),
)
}
pub fn preview_symbolic_for_target_with_cache(
layout: &StateLayout,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<ProjectionResolution<SymbolicProjectionView>> {
let source_fingerprint = fingerprint_for_inputs(&loaded.sources, loaded.pod_identity_active)?;
preview_symbolic_with_precomputed_fingerprint(layout, None, loaded, target, &source_fingerprint)
}
pub(crate) fn preview_symbolic_with_precomputed_fingerprint(
layout: &StateLayout,
shared_db: Option<&db::StateDb>,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
source_fingerprint: &str,
) -> Result<ProjectionResolution<SymbolicProjectionView>> {
resolve_cached_projection(
layout,
shared_db,
target,
ProjectionFormat::Symbolic,
source_fingerprint,
true,
|| compile_loaded_symbolic_projection(loaded, target),
)
}
pub fn preview_bundle_for_target_with_cache(
layout: &StateLayout,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<ProjectionResolution<BundleProjectionView>> {
let source_fingerprint = fingerprint_for_inputs(&loaded.sources, loaded.pod_identity_active)?;
preview_bundle_with_precomputed_fingerprint(layout, None, loaded, target, &source_fingerprint)
}
pub(crate) fn preview_bundle_with_precomputed_fingerprint(
layout: &StateLayout,
shared_db: Option<&db::StateDb>,
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
source_fingerprint: &str,
) -> Result<ProjectionResolution<BundleProjectionView>> {
resolve_cached_projection(
layout,
shared_db,
target,
ProjectionFormat::Bundle,
source_fingerprint,
true,
|| {
let narrative = preview_with_precomputed_fingerprint(
layout,
shared_db,
loaded,
target,
source_fingerprint,
false,
)?;
Ok(compile_bundle_projection(&narrative.value))
},
)
}
pub(crate) fn bundle_view_from_store(store: &CompiledStateStore) -> BundleProjectionView {
compile_bundle_projection(store)
}
fn resolve_cached_projection<T, F>(
layout: &StateLayout,
shared_db: Option<&db::StateDb>,
target: ProjectionTarget,
format: ProjectionFormat,
source_fingerprint: &str,
record_event: bool,
compute: F,
) -> Result<ProjectionResolution<T>>
where
T: Serialize + DeserializeOwned,
F: FnOnce() -> Result<T>,
{
let observed_at_epoch_s = session_state::now_epoch_s()?;
let tool_surface_fingerprint = current_tool_surface_fingerprint();
let owned_db = match shared_db {
Some(_) => None,
None => Some(db::StateDb::open(&layout.state_db_path())?),
};
let db: &db::StateDb = shared_db.unwrap_or_else(|| {
owned_db
.as_ref()
.expect("owned_db populated when shared_db is None")
});
let cached = db::projection_cache::read_entry(
db.conn(),
target.as_str(),
format.as_str(),
source_fingerprint,
&tool_surface_fingerprint,
)?;
let (value, cache_status) = if let Some(entry) = cached {
match serde_json::from_str(&entry.payload_json) {
Ok(value) => (value, "hit"),
Err(_) => {
let value = compute()?;
persist_cached_projection(
db.conn(),
observed_at_epoch_s,
target,
format,
source_fingerprint,
&tool_surface_fingerprint,
&value,
)?;
(value, "miss")
}
}
} else {
let value = compute()?;
persist_cached_projection(
db.conn(),
observed_at_epoch_s,
target,
format,
source_fingerprint,
&tool_surface_fingerprint,
&value,
)?;
(value, "miss")
};
if record_event {
let session_id = match shared_db {
Some(db) => session_state::load_session_id_from_shared_db(db, layout)?,
None => session_state::load_session_id(layout)?,
};
db::projection_cache::record_event(
db.conn(),
&db::projection_cache::ProjectionCacheEventRecord {
id: None,
observed_at_epoch_s,
session_id,
target: target.as_str().to_owned(),
format: format.as_str().to_owned(),
source_fingerprint: source_fingerprint.to_owned(),
tool_surface_fingerprint: tool_surface_fingerprint.clone(),
cache_status: cache_status.to_owned(),
},
)?;
}
Ok(ProjectionResolution {
value,
cadence: ProjectionFormatCadenceCurrent {
target: target.as_str(),
format: format.as_str(),
cache_status,
observed_at_epoch_s,
source_fingerprint: source_fingerprint.to_owned(),
tool_surface_fingerprint,
},
})
}
fn persist_cached_projection<T: Serialize>(
conn: &rusqlite::Connection,
observed_at_epoch_s: u64,
target: ProjectionTarget,
format: ProjectionFormat,
source_fingerprint: &str,
tool_surface_fingerprint: &str,
value: &T,
) -> Result<()> {
db::projection_cache::upsert_entry(
conn,
&db::projection_cache::ProjectionCacheEntryRecord {
id: None,
observed_at_epoch_s,
target: target.as_str().to_owned(),
format: format.as_str().to_owned(),
source_fingerprint: source_fingerprint.to_owned(),
tool_surface_fingerprint: tool_surface_fingerprint.to_owned(),
payload_json: serde_json::to_string(value)?,
},
)
}
fn compile_from_runtime_for_target(
repo_root: &Path,
layout: &StateLayout,
locality_id: &str,
target: ProjectionTarget,
) -> Result<CompiledStateStore> {
let loaded = runtime_state::load_runtime_state(repo_root, layout, locality_id)?;
preview_for_target_with_cache(layout, &loaded, target).map(|resolution| resolution.value)
}
fn compile_loaded_runtime_for_target(
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<CompiledStateStore> {
let mut compiled = compile_runtime_projection(
&loaded.state,
&loaded.sources,
target,
loaded.pod_identity_active,
)?;
dedupe_compiled_projection(&mut compiled);
compiled.projection_digests = Some(compute_projection_digests(&compiled));
Ok(compiled)
}
fn compile_loaded_symbolic_projection(
loaded: &runtime_state::LoadedRuntimeState,
target: ProjectionTarget,
) -> Result<SymbolicProjectionView> {
let mut projection = compile_symbolic_projection(
&loaded.state,
&loaded.sources,
target,
loaded.pod_identity_active,
)?;
if let Some(anchor) = loaded.execution_gates.view.attention_anchor.as_ref() {
projection.facts.push(SymbolicFact {
surface: "execution_gates".to_owned(),
kind: "attention_anchor".to_owned(),
ordinal: Some(anchor.index),
text: anchor.text.clone(),
});
}
Ok(projection)
}
fn compile_runtime_projection(
state: &runtime_state::RuntimeState,
sources: &runtime_state::RuntimeSourceSurfaces,
target: ProjectionTarget,
pod_identity_active: bool,
) -> Result<CompiledStateStore> {
let bounds = default_projection_bounds();
let handoff_target = handoff_target(target);
let mut compiled = CompiledStateStore {
schema_version: SCHEMA_VERSION,
target,
source_fingerprint: fingerprint_for_inputs(sources, pod_identity_active)?,
pod_identity_active,
projection_digests: None,
effective_memory: CompiledMemoryView {
profile: project_memory_entries(
&state.memory.profile,
bounds.max_active_memory_entries_per_scope,
),
locality: project_memory_entries(
&state.memory.locality,
bounds.max_active_memory_entries_per_scope,
),
pod: project_memory_entries(
&state.memory.pod,
bounds.max_active_memory_entries_per_scope,
),
branch: project_memory_entries(
&state.memory.branch,
bounds.max_active_memory_entries_per_scope,
),
clone: project_memory_entries(
&state.memory.clone,
bounds.max_active_memory_entries_per_scope,
),
},
handoff: project_handoff(&state.handoff, bounds, handoff_target),
};
dedupe_compiled_projection(&mut compiled);
compiled.projection_digests = Some(compute_projection_digests(&compiled));
Ok(compiled)
}
fn compile_symbolic_projection(
state: &runtime_state::RuntimeState,
sources: &runtime_state::RuntimeSourceSurfaces,
target: ProjectionTarget,
pod_identity_active: bool,
) -> Result<SymbolicProjectionView> {
let bounds = default_projection_bounds();
let handoff_target = handoff_target(target);
let mut facts = Vec::new();
if pod_identity_active {
append_memory_facts(
&mut facts,
"pod_memory",
project_active_memory_entries(
&state.memory.pod,
bounds.max_active_memory_entries_per_scope,
),
);
append_memory_facts(
&mut facts,
"profile_memory",
project_active_memory_entries(
&state.memory.profile,
bounds.max_active_memory_entries_per_scope,
),
);
append_memory_facts(
&mut facts,
"locality_memory",
project_active_memory_entries(
&state.memory.locality,
bounds.max_active_memory_entries_per_scope,
),
);
} else {
append_memory_facts(
&mut facts,
"profile_memory",
project_active_memory_entries(
&state.memory.profile,
bounds.max_active_memory_entries_per_scope,
),
);
append_memory_facts(
&mut facts,
"locality_memory",
project_active_memory_entries(
&state.memory.locality,
bounds.max_active_memory_entries_per_scope,
),
);
append_memory_facts(
&mut facts,
"pod_memory",
project_active_memory_entries(
&state.memory.pod,
bounds.max_active_memory_entries_per_scope,
),
);
}
append_memory_facts(
&mut facts,
"branch_memory",
project_active_memory_entries(
&state.memory.branch,
bounds.max_active_memory_entries_per_scope,
),
);
append_memory_facts(
&mut facts,
"clone_memory",
project_active_memory_entries(
&state.memory.clone,
bounds.max_active_memory_entries_per_scope,
),
);
if !state.handoff.title.trim().is_empty() {
facts.push(SymbolicFact {
surface: "handoff_title".to_owned(),
kind: "title".to_owned(),
ordinal: None,
text: state.handoff.title.clone(),
});
}
append_handoff_facts(
&mut facts,
"handoff_immediate_actions",
project_active_handoff_items(
&state.handoff.immediate_actions,
bounds.max_active_handoff_items_per_section,
),
);
if handoff_target.include_completed_state {
append_handoff_facts(
&mut facts,
"handoff_completed_state",
project_active_handoff_items(
&state.handoff.completed_state,
bounds.max_active_handoff_items_per_section,
),
);
}
append_handoff_facts(
&mut facts,
"handoff_operational_guardrails",
project_active_handoff_items(
&state.handoff.operational_guardrails,
bounds.max_active_handoff_items_per_section,
),
);
if handoff_target.include_key_files {
append_handoff_facts(
&mut facts,
"handoff_key_files",
project_active_handoff_items(
&state.handoff.key_files,
bounds.max_active_handoff_items_per_section,
),
);
}
if handoff_target.include_definition_of_done {
append_handoff_facts(
&mut facts,
"handoff_definition_of_done",
project_active_handoff_items(
&state.handoff.definition_of_done,
bounds.max_active_handoff_items_per_section,
),
);
}
Ok(SymbolicProjectionView {
target,
source_fingerprint: fingerprint_for_inputs(sources, pod_identity_active)?,
facts,
})
}
fn compile_bundle_projection(store: &CompiledStateStore) -> BundleProjectionView {
let mut sections = Vec::new();
push_bundle_section(
&mut sections,
BundleSectionKind::Do,
store.handoff.immediate_actions.clone(),
);
push_bundle_section(
&mut sections,
BundleSectionKind::Remember,
bundle_memory_items(&store.effective_memory, store.pod_identity_active),
);
push_bundle_section(
&mut sections,
BundleSectionKind::Rules,
store.handoff.operational_guardrails.clone(),
);
push_bundle_section(
&mut sections,
BundleSectionKind::Files,
store.handoff.key_files.clone(),
);
push_bundle_section(
&mut sections,
BundleSectionKind::CloseOut,
store.handoff.definition_of_done.clone(),
);
let task = bundle_task(&store.handoff.title, store.target);
let markdown = render_bundle_markdown(&task, §ions);
BundleProjectionView {
target: store.target,
source_fingerprint: store.source_fingerprint.clone(),
task,
sections,
markdown,
}
}
fn handoff_target(target: ProjectionTarget) -> HandoffProjectionTarget {
match target {
ProjectionTarget::Default => HandoffProjectionTarget {
include_completed_state: true,
include_key_files: true,
include_definition_of_done: true,
},
ProjectionTarget::Planning => HandoffProjectionTarget {
include_completed_state: false,
include_key_files: false,
include_definition_of_done: true,
},
ProjectionTarget::Session => HandoffProjectionTarget {
include_completed_state: false,
include_key_files: false,
include_definition_of_done: false,
},
}
}
#[derive(Debug, Clone, Copy)]
struct HandoffProjectionTarget {
include_completed_state: bool,
include_key_files: bool,
include_definition_of_done: bool,
}
fn default_projection_bounds() -> ProjectionBounds {
ProjectionBounds {
max_active_memory_entries_per_scope: DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE,
max_active_handoff_items_per_section: DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION,
}
}
pub(crate) fn fingerprint_for_inputs(
sources: &runtime_state::RuntimeSourceSurfaces,
pod_identity_active: bool,
) -> Result<String> {
let payload = serde_json::to_vec(&FingerprintInputs {
profile_memory: FingerprintSurface::from(&sources.profile_memory),
locality_memory: FingerprintSurface::from(&sources.locality_memory),
pod_memory: FingerprintSurface::from(&sources.pod_memory),
branch_memory: FingerprintSurface::from(&sources.branch_memory),
clone_memory: FingerprintSurface::from(&sources.clone_memory),
execution_gates: FingerprintSurface::from(&sources.execution_gates),
handoff: FingerprintSurface::from(&sources.handoff),
pod_identity_active,
})?;
let mut hasher = Sha256::new();
hasher.update(payload);
Ok(format!("{:x}", hasher.finalize()))
}
fn project_memory_entries(
entries: &[runtime_state::RuntimeMemoryEntry],
max_active_entries: usize,
) -> Vec<String> {
project_active_memory_entries(entries, max_active_entries)
.into_iter()
.map(runtime_state::RuntimeMemoryEntry::projection_text)
.collect()
}
fn project_handoff(
state: &runtime_state::RuntimeHandoffState,
bounds: ProjectionBounds,
target: HandoffProjectionTarget,
) -> CompiledHandoffView {
CompiledHandoffView {
title: state.title.clone(),
immediate_actions: project_handoff_items(
&state.immediate_actions,
bounds.max_active_handoff_items_per_section,
),
completed_state: if target.include_completed_state {
project_handoff_items(
&state.completed_state,
bounds.max_active_handoff_items_per_section,
)
} else {
Vec::new()
},
operational_guardrails: project_handoff_items(
&state.operational_guardrails,
bounds.max_active_handoff_items_per_section,
),
key_files: if target.include_key_files {
project_handoff_items(
&state.key_files,
bounds.max_active_handoff_items_per_section,
)
} else {
Vec::new()
},
definition_of_done: if target.include_definition_of_done {
project_handoff_items(
&state.definition_of_done,
bounds.max_active_handoff_items_per_section,
)
} else {
Vec::new()
},
}
}
fn dedupe_compiled_projection(store: &mut CompiledStateStore) {
let mut seen = HashSet::new();
if store.pod_identity_active {
dedupe_strings(&mut store.effective_memory.pod, &mut seen);
dedupe_strings(&mut store.effective_memory.profile, &mut seen);
dedupe_strings(&mut store.effective_memory.locality, &mut seen);
} else {
dedupe_strings(&mut store.effective_memory.profile, &mut seen);
dedupe_strings(&mut store.effective_memory.locality, &mut seen);
dedupe_strings(&mut store.effective_memory.pod, &mut seen);
}
dedupe_strings(&mut store.effective_memory.branch, &mut seen);
dedupe_strings(&mut store.effective_memory.clone, &mut seen);
dedupe_strings(&mut store.handoff.immediate_actions, &mut seen);
dedupe_strings(&mut store.handoff.completed_state, &mut seen);
dedupe_strings(&mut store.handoff.operational_guardrails, &mut seen);
dedupe_strings(&mut store.handoff.key_files, &mut seen);
dedupe_strings(&mut store.handoff.definition_of_done, &mut seen);
}
fn dedupe_strings(items: &mut Vec<String>, seen: &mut HashSet<String>) {
items.retain(|item| seen.insert(item.clone()));
}
fn project_handoff_items(
items: &[runtime_state::RuntimeHandoffItem],
max_active_items: usize,
) -> Vec<String> {
project_active_handoff_items(items, max_active_items)
.into_iter()
.map(|item| item.text.clone())
.collect()
}
fn project_active_memory_entries(
entries: &[runtime_state::RuntimeMemoryEntry],
max_active_entries: usize,
) -> Vec<&runtime_state::RuntimeMemoryEntry> {
collect_active_items(
entries
.iter()
.filter(|entry| runtime_memory_entry_is_active(entry)),
max_active_entries,
runtime_state::RuntimeMemoryEntry::projection_text,
)
}
fn runtime_memory_entry_is_active(entry: &runtime_state::RuntimeMemoryEntry) -> bool {
if !entry.lifecycle.is_active() {
return false;
}
let Some(expires_at) = entry.expires_at.as_deref() else {
return true;
};
match timestamps::parse_rfc3339(expires_at) {
Some(expires_at) => expires_at > timestamps::now_utc(),
None => true,
}
}
fn project_active_handoff_items(
items: &[runtime_state::RuntimeHandoffItem],
max_active_items: usize,
) -> Vec<&runtime_state::RuntimeHandoffItem> {
collect_active_items(
items.iter().filter(|item| item.lifecycle.is_active()),
max_active_items,
|item| item.text.clone(),
)
}
fn collect_active_items<'a, T, I, F>(items: I, max_active_items: usize, key: F) -> Vec<&'a T>
where
I: IntoIterator<Item = &'a T>,
F: Fn(&T) -> String,
{
let mut seen = HashSet::new();
let mut selected = Vec::new();
for item in items {
let marker = key(item);
if marker.trim().is_empty() {
continue;
}
if seen.insert(marker) {
selected.push(item);
if selected.len() == max_active_items {
break;
}
}
}
selected
}
fn append_memory_facts(
facts: &mut Vec<SymbolicFact>,
surface: &str,
entries: Vec<&runtime_state::RuntimeMemoryEntry>,
) {
for (index, entry) in entries.into_iter().enumerate() {
facts.push(SymbolicFact {
surface: surface.to_owned(),
kind: symbolic_memory_kind(entry),
ordinal: Some(index + 1),
text: entry.text.clone(),
});
}
}
fn append_handoff_facts(
facts: &mut Vec<SymbolicFact>,
surface: &str,
items: Vec<&runtime_state::RuntimeHandoffItem>,
) {
for (index, item) in items.into_iter().enumerate() {
facts.push(SymbolicFact {
surface: surface.to_owned(),
kind: "item".to_owned(),
ordinal: Some(index + 1),
text: item.text.clone(),
});
}
}
fn symbolic_memory_kind(entry: &runtime_state::RuntimeMemoryEntry) -> String {
match &entry.origin {
runtime_state::RuntimeMemoryOrigin::Narrative => "narrative".to_owned(),
runtime_state::RuntimeMemoryOrigin::Structured { entry_type, .. } => entry_type.clone(),
}
}
fn bundle_task(title: &str, target: ProjectionTarget) -> String {
let trimmed = title.trim();
if trimmed.is_empty() {
return format!("{} session bundle", target.as_str());
}
trimmed
.strip_prefix("Next Session:")
.unwrap_or(trimmed)
.trim()
.to_owned()
}
fn bundle_memory_items(view: &CompiledMemoryView, pod_identity_active: bool) -> Vec<String> {
let mut items = Vec::new();
if pod_identity_active {
items.extend(view.pod.iter().map(|item| format!("Pod: {item}")));
items.extend(view.profile.iter().map(|item| format!("Profile: {item}")));
items.extend(view.locality.iter().map(|item| format!("Project: {item}")));
} else {
items.extend(view.profile.iter().map(|item| format!("Profile: {item}")));
items.extend(view.locality.iter().map(|item| format!("Project: {item}")));
items.extend(view.pod.iter().map(|item| format!("Pod: {item}")));
}
items.extend(
view.branch
.iter()
.map(|item| format!("Work stream: {item}")),
);
items.extend(view.clone.iter().map(|item| format!("Workspace: {item}")));
items
}
fn push_bundle_section(
sections: &mut Vec<BundleSection>,
kind: BundleSectionKind,
items: Vec<String>,
) {
if items.is_empty() {
return;
}
sections.push(BundleSection {
kind,
title: kind.title().to_owned(),
items,
});
}
#[cfg_attr(not(test), allow(dead_code))]
fn render_symbolic_fact(fact: &SymbolicFact) -> String {
match fact.ordinal {
Some(ordinal) => format!("{}|{}|{}|{}", fact.surface, fact.kind, ordinal, fact.text),
None => format!("{}|{}|{}", fact.surface, fact.kind, fact.text),
}
}
pub fn render_bundle_markdown(task: &str, sections: &[BundleSection]) -> String {
let mut body = String::from("# CCD Bundle\n\n");
body.push_str("Task: ");
body.push_str(task);
body.push('\n');
for section in sections {
body.push('\n');
body.push_str("## ");
body.push_str(§ion.title);
body.push('\n');
for item in §ion.items {
body.push_str("- ");
body.push_str(item);
body.push('\n');
}
}
body
}
fn append_section(body: &mut String, title: &str, items: &[String]) {
if items.is_empty() {
return;
}
if !body.is_empty() {
body.push('\n');
}
body.push_str("### ");
body.push_str(title);
body.push_str("\n\n");
for item in items {
body.push_str("- ");
body.push_str(item);
body.push('\n');
}
}
#[derive(Serialize)]
struct FingerprintInputs<'a> {
profile_memory: FingerprintSurface<'a>,
locality_memory: FingerprintSurface<'a>,
pod_memory: FingerprintSurface<'a>,
branch_memory: FingerprintSurface<'a>,
clone_memory: FingerprintSurface<'a>,
execution_gates: FingerprintSurface<'a>,
handoff: FingerprintSurface<'a>,
pod_identity_active: bool,
}
#[derive(Serialize)]
struct FingerprintSurface<'a> {
status: &'static str,
content: &'a str,
}
impl<'a> From<&'a runtime_state::RuntimeTextSurface> for FingerprintSurface<'a> {
fn from(value: &'a runtime_state::RuntimeTextSurface) -> Self {
Self {
status: match value.status {
runtime_state::RuntimeTextSurfaceStatus::LoadedNative => "loaded",
other => other.as_str(),
},
content: &value.content,
}
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use tempfile::tempdir;
use super::*;
use crate::memory::entries::StructuredMemoryEntry;
use crate::profile::ProfileName;
use crate::state::runtime::{
LoadedRuntimeExecutionGates, LoadedRuntimeRecoveryState, LoadedRuntimeState,
RuntimeHandoffItem, RuntimeHandoffState, RuntimeLifecycle, RuntimeMemoryEntry,
RuntimeMemoryState, RuntimeRecoveryState, RuntimeRecoverySurface, RuntimeRecoverySurfaces,
RuntimeSourceSurfaces, RuntimeState, RuntimeTextSurface, RuntimeTextSurfaceStatus,
};
use crate::state::session_gates;
fn missing_clone_memory_surface() -> RuntimeTextSurface {
RuntimeTextSurface {
kind: "clone_memory",
path: PathBuf::from("/tmp/clone-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
}
}
fn missing_pod_memory_surface() -> RuntimeTextSurface {
RuntimeTextSurface {
kind: "pod_memory",
path: PathBuf::from("/tmp/pod-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
}
}
fn missing_branch_memory_surface() -> RuntimeTextSurface {
RuntimeTextSurface {
kind: "branch_memory",
path: PathBuf::from("/tmp/branch-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
}
}
fn missing_execution_gates_surface() -> RuntimeTextSurface {
RuntimeTextSurface {
kind: "execution_gates",
path: PathBuf::from("/tmp/state.db"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
}
}
fn missing_execution_gates() -> LoadedRuntimeExecutionGates {
LoadedRuntimeExecutionGates {
source: missing_execution_gates_surface(),
view: session_gates::ExecutionGatesView {
path: "/tmp/state.db".to_owned(),
status: "missing",
seeded_from: None,
revision: None,
total_count: 0,
unfinished_count: 0,
attention_anchor: None,
gates: Vec::new(),
},
}
}
#[test]
fn projects_runtime_state_into_compiled_views() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![
RuntimeMemoryEntry::narrative("Keep projections bounded."),
RuntimeMemoryEntry {
lifecycle: RuntimeLifecycle::Inactive,
..RuntimeMemoryEntry::narrative("Skip stale notes.")
},
RuntimeMemoryEntry::narrative("Keep projections bounded."),
],
locality: vec![RuntimeMemoryEntry::from_structured_entry(
StructuredMemoryEntry {
id: "mem_rule".to_owned(),
entry_type: "rule".to_owned(),
state: "active".to_owned(),
created_at: "2026-03-10T10:00:00Z".to_owned(),
last_touched_session: 1,
origin: "manual".to_owned(),
superseded_at: None,
decay_class: None,
expires_at: None,
tags: Vec::new(),
source_ref: None,
supersedes: Vec::new(),
content: "Prefer deterministic writes.".to_owned(),
},
)],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Runtime".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Add runtime-state scaffolding.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Archived work.".to_owned(),
lifecycle: RuntimeLifecycle::Inactive,
}],
operational_guardrails: Vec::new(),
key_files: Vec::new(),
definition_of_done: Vec::new(),
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Default, false)
.expect("compiled projection");
assert_eq!(compiled.target, ProjectionTarget::Default);
assert_eq!(
compiled.effective_memory.profile,
vec!["Keep projections bounded.".to_owned()]
);
assert_eq!(
compiled.effective_memory.locality,
vec!["rule: Prefer deterministic writes.".to_owned()]
);
assert_eq!(compiled.handoff.title, "Next Session: Runtime");
assert_eq!(
compiled.handoff.immediate_actions,
vec!["Add runtime-state scaffolding.".to_owned()]
);
assert!(compiled.handoff.completed_state.is_empty());
assert!(!compiled.source_fingerprint.is_empty());
}
#[test]
fn projects_runtime_state_without_expired_active_memory_entries() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![
RuntimeMemoryEntry::from_structured_entry(StructuredMemoryEntry {
id: "mem_expired".to_owned(),
entry_type: "rule".to_owned(),
state: "active".to_owned(),
created_at: "2026-03-10T10:00:00Z".to_owned(),
last_touched_session: 1,
origin: "manual".to_owned(),
superseded_at: None,
decay_class: Some("active".to_owned()),
expires_at: Some("2000-01-01T00:00:00Z".to_owned()),
tags: Vec::new(),
source_ref: None,
supersedes: Vec::new(),
content: "Expired rule should stay out of preload.".to_owned(),
}),
RuntimeMemoryEntry::from_structured_entry(StructuredMemoryEntry {
id: "mem_current".to_owned(),
entry_type: "rule".to_owned(),
state: "active".to_owned(),
created_at: "2026-03-10T11:00:00Z".to_owned(),
last_touched_session: 2,
origin: "manual".to_owned(),
superseded_at: None,
decay_class: Some("stable".to_owned()),
expires_at: Some("2999-01-01T00:00:00Z".to_owned()),
tags: Vec::new(),
source_ref: None,
supersedes: Vec::new(),
content: "Future rule should remain in preload.".to_owned(),
}),
],
locality: Vec::new(),
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState::default(),
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Default, false)
.expect("compiled projection");
assert_eq!(
compiled.effective_memory.profile,
vec!["rule: Future rule should remain in preload.".to_owned()]
);
}
#[test]
fn unparseable_expires_at_keeps_entry_active() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::from_structured_entry(
StructuredMemoryEntry {
id: "mem_bad_ts".to_owned(),
entry_type: "rule".to_owned(),
state: "active".to_owned(),
created_at: "2026-03-10T10:00:00Z".to_owned(),
last_touched_session: 1,
origin: "manual".to_owned(),
superseded_at: None,
decay_class: Some("active".to_owned()),
expires_at: Some("not-a-timestamp".to_owned()),
tags: Vec::new(),
source_ref: None,
supersedes: Vec::new(),
content: "Entry with unparseable expiry stays active.".to_owned(),
},
)],
locality: Vec::new(),
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState::default(),
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Default, false)
.expect("compiled projection");
assert_eq!(
compiled.effective_memory.profile,
vec!["rule: Entry with unparseable expiry stays active.".to_owned()]
);
}
#[test]
fn ensure_for_runtime_projects_loaded_state_without_reloading_authored_files() {
let temp = tempdir().expect("tempdir");
let layout = StateLayout::new(
temp.path().join(".ccd"),
temp.path().join(".git/ccd"),
ProfileName::new("main").expect("profile"),
);
let loaded = LoadedRuntimeState {
state: RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative(
"Use the loaded runtime view.",
)],
locality: Vec::new(),
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Runtime-first projection".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Avoid adapter rereads.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: Vec::new(),
operational_guardrails: Vec::new(),
key_files: Vec::new(),
definition_of_done: Vec::new(),
},
},
sources: RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/virtual/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "# Profile Memory\n\n- Use the loaded runtime view.\n".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/virtual/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Missing,
content: String::new(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/virtual/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "# Next Session: Runtime-first projection\n".to_owned(),
migrated_from: None,
},
},
execution_gates: missing_execution_gates(),
recovery: LoadedRuntimeRecoveryState {
state: RuntimeRecoveryState::default(),
sources: RuntimeRecoverySurfaces {
checkpoint: RuntimeRecoverySurface {
kind: "checkpoint",
path: PathBuf::from("/virtual/checkpoint.json"),
status: "missing",
},
working_buffer: RuntimeRecoverySurface {
kind: "working_buffer",
path: PathBuf::from("/virtual/working_buffer.md"),
status: "missing",
},
},
},
pod_identity_active: false,
};
let prepared = ensure_for_runtime(&layout, &loaded).expect("prepare compiled state");
assert_eq!(prepared.surface.status, "computed");
assert_eq!(prepared.surface.target, "session");
assert_eq!(prepared.store.target, ProjectionTarget::Session);
assert_eq!(
prepared.store.effective_memory.profile,
vec!["Use the loaded runtime view.".to_owned()]
);
assert_eq!(
prepared.store.handoff.immediate_actions,
vec!["Avoid adapter rereads.".to_owned()]
);
}
#[test]
fn projection_applies_default_active_state_bounds_after_filtering_and_dedupe() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: (0..(DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE + 3))
.map(|index| RuntimeMemoryEntry::narrative(format!("Profile rule {index:02}")))
.chain(std::iter::once(RuntimeMemoryEntry::narrative(
"Profile rule 00".to_owned(),
)))
.collect(),
locality: (0..(DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE + 2))
.map(|index| RuntimeMemoryEntry::narrative(format!("Repo note {index:02}")))
.collect(),
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Bounded projection".to_owned(),
immediate_actions: (0..(DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION + 3))
.map(|index| RuntimeHandoffItem {
text: format!("Immediate action {index:02}"),
lifecycle: RuntimeLifecycle::Active,
})
.collect(),
completed_state: Vec::new(),
operational_guardrails: Vec::new(),
key_files: (0..(DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION + 2))
.map(|index| RuntimeHandoffItem {
text: format!("src/file_{index:02}.rs"),
lifecycle: RuntimeLifecycle::Active,
})
.collect(),
definition_of_done: Vec::new(),
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Default, false)
.expect("compiled projection");
assert_eq!(
compiled.effective_memory.profile.len(),
DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE
);
assert_eq!(
compiled.effective_memory.profile[0],
"Profile rule 00".to_owned()
);
assert_eq!(
compiled.effective_memory.profile.last().unwrap(),
&format!(
"Profile rule {:02}",
DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE - 1
)
);
assert_eq!(
compiled.effective_memory.locality.len(),
DEFAULT_MAX_ACTIVE_MEMORY_ENTRIES_PER_SCOPE
);
assert_eq!(
compiled.handoff.immediate_actions.len(),
DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION
);
assert_eq!(
compiled.handoff.immediate_actions.last().unwrap(),
&format!(
"Immediate action {:02}",
DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION - 1
)
);
assert_eq!(
compiled.handoff.key_files.len(),
DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION
);
assert_eq!(
compiled.handoff.key_files.last().unwrap(),
&format!(
"src/file_{:02}.rs",
DEFAULT_MAX_ACTIVE_HANDOFF_ITEMS_PER_SECTION - 1
)
);
}
#[test]
fn planning_target_omits_completed_state_and_key_files() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Retain operator rules.")],
locality: vec![RuntimeMemoryEntry::narrative("Retain repo lessons.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Plan the slice".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Review the backlog.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Completed work should stay out of planning.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep projections fail-closed.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: vec![RuntimeHandoffItem {
text: "`src/state/runtime_export.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Scoped target is explicit.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Planning, false)
.expect("compiled planning projection");
assert_eq!(compiled.target, ProjectionTarget::Planning);
assert_eq!(
compiled.effective_memory.profile,
vec!["Retain operator rules.".to_owned()]
);
assert_eq!(
compiled.handoff.immediate_actions,
vec!["Review the backlog.".to_owned()]
);
assert_eq!(
compiled.handoff.operational_guardrails,
vec!["Keep projections fail-closed.".to_owned()]
);
assert_eq!(
compiled.handoff.definition_of_done,
vec!["Scoped target is explicit.".to_owned()]
);
assert!(compiled.handoff.completed_state.is_empty());
assert!(compiled.handoff.key_files.is_empty());
}
#[test]
fn session_target_omits_completed_state_key_files_and_definition_of_done() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Retain operator rules.")],
locality: vec![RuntimeMemoryEntry::narrative("Retain repo lessons.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Start the slice".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Review the backlog.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Completed work should stay out of the start bundle.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep projections fail-closed.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: vec![RuntimeHandoffItem {
text: "`src/state/runtime_export.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Scoped target is explicit.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Session, false)
.expect("compiled session projection");
assert_eq!(compiled.target, ProjectionTarget::Session);
assert_eq!(
compiled.handoff.immediate_actions,
vec!["Review the backlog.".to_owned()]
);
assert_eq!(
compiled.handoff.operational_guardrails,
vec!["Keep projections fail-closed.".to_owned()]
);
assert!(compiled.handoff.completed_state.is_empty());
assert!(compiled.handoff.key_files.is_empty());
assert!(compiled.handoff.definition_of_done.is_empty());
}
#[test]
fn narrative_projection_dedupes_repeated_lines_across_surfaces() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Keep projections bounded.")],
locality: vec![RuntimeMemoryEntry::narrative("Keep projections bounded.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Dedupe".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Keep projections bounded.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: Vec::new(),
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep projections bounded.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: Vec::new(),
definition_of_done: vec![RuntimeHandoffItem {
text: "Keep projections bounded.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let compiled =
compile_runtime_projection(&state, &sources, ProjectionTarget::Planning, false)
.expect("compiled planning projection");
assert_eq!(
compiled.effective_memory.profile,
vec!["Keep projections bounded.".to_owned()]
);
assert!(compiled.effective_memory.locality.is_empty());
assert!(compiled.handoff.immediate_actions.is_empty());
assert!(compiled.handoff.operational_guardrails.is_empty());
assert!(compiled.handoff.definition_of_done.is_empty());
}
#[test]
fn symbolic_projection_uses_fact_kinds_and_default_target_sections() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![
RuntimeMemoryEntry::narrative("Retain operator rules."),
RuntimeMemoryEntry::from_structured_entry(StructuredMemoryEntry {
id: "mem_rule".to_owned(),
entry_type: "rule".to_owned(),
state: "active".to_owned(),
created_at: "2026-03-10T12:00:00Z".to_owned(),
last_touched_session: 7,
origin: "manual".to_owned(),
superseded_at: None,
decay_class: None,
expires_at: None,
tags: vec!["projection".to_owned()],
source_ref: None,
supersedes: Vec::new(),
content: "Prefer deterministic writes.".to_owned(),
}),
],
locality: vec![RuntimeMemoryEntry::narrative("Keep repo state bounded.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Evaluate symbolic facts".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Measure prompt entropy.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Narrative preview already works.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep the cache derived.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: vec![RuntimeHandoffItem {
text: "`src/state/compiled.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Decision is documented.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let symbolic =
compile_symbolic_projection(&state, &sources, ProjectionTarget::Default, false)
.unwrap();
assert_eq!(symbolic.target, ProjectionTarget::Default);
assert!(symbolic.facts.contains(&SymbolicFact {
surface: "profile_memory".to_owned(),
kind: "narrative".to_owned(),
ordinal: Some(1),
text: "Retain operator rules.".to_owned(),
}));
assert!(symbolic.facts.contains(&SymbolicFact {
surface: "profile_memory".to_owned(),
kind: "rule".to_owned(),
ordinal: Some(2),
text: "Prefer deterministic writes.".to_owned(),
}));
assert!(symbolic.facts.contains(&SymbolicFact {
surface: "handoff_completed_state".to_owned(),
kind: "item".to_owned(),
ordinal: Some(1),
text: "Narrative preview already works.".to_owned(),
}));
assert!(symbolic.facts.contains(&SymbolicFact {
surface: "handoff_key_files".to_owned(),
kind: "item".to_owned(),
ordinal: Some(1),
text: "`src/state/compiled.rs`".to_owned(),
}));
}
#[test]
fn symbolic_planning_target_omits_completed_state_and_key_files() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Retain operator rules.")],
locality: vec![RuntimeMemoryEntry::narrative("Retain repo lessons.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Plan the slice".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Review the backlog.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Completed work should stay out of planning.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep projections fail-closed.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: vec![RuntimeHandoffItem {
text: "`src/state/runtime_export.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Scoped target is explicit.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let symbolic =
compile_symbolic_projection(&state, &sources, ProjectionTarget::Planning, false)
.unwrap();
assert_eq!(symbolic.target, ProjectionTarget::Planning);
assert!(!symbolic
.facts
.iter()
.any(|fact| fact.surface == "handoff_completed_state"));
assert!(!symbolic
.facts
.iter()
.any(|fact| fact.surface == "handoff_key_files"));
assert_eq!(
render_symbolic_content(&symbolic),
"\
profile_memory|narrative|1|Retain operator rules.\n\
locality_memory|narrative|1|Retain repo lessons.\n\
handoff_title|title|Next Session: Plan the slice\n\
handoff_immediate_actions|item|1|Review the backlog.\n\
handoff_operational_guardrails|item|1|Keep projections fail-closed.\n\
handoff_definition_of_done|item|1|Scoped target is explicit."
);
}
#[test]
fn symbolic_session_target_omits_definition_of_done_and_key_files() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Retain operator rules.")],
locality: vec![RuntimeMemoryEntry::narrative("Retain repo lessons.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Start the slice".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Review the backlog.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Completed work should stay out of the start bundle.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: vec![RuntimeHandoffItem {
text: "Keep projections fail-closed.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
key_files: vec![RuntimeHandoffItem {
text: "`src/state/runtime_export.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Scoped target is explicit.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let sources = RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "profile".to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "repo".to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: "handoff".to_owned(),
migrated_from: None,
},
};
let symbolic =
compile_symbolic_projection(&state, &sources, ProjectionTarget::Session, false)
.unwrap();
assert_eq!(symbolic.target, ProjectionTarget::Session);
assert!(!symbolic
.facts
.iter()
.any(|fact| fact.surface == "handoff_completed_state"));
assert!(!symbolic
.facts
.iter()
.any(|fact| fact.surface == "handoff_key_files"));
assert!(!symbolic
.facts
.iter()
.any(|fact| fact.surface == "handoff_definition_of_done"));
assert_eq!(
render_symbolic_content(&symbolic),
"\
profile_memory|narrative|1|Retain operator rules.\n\
locality_memory|narrative|1|Retain repo lessons.\n\
handoff_title|title|Next Session: Start the slice\n\
handoff_immediate_actions|item|1|Review the backlog.\n\
handoff_operational_guardrails|item|1|Keep projections fail-closed."
);
}
fn make_test_sources(
profile: &str,
repo: &str,
_focus: &str,
handoff: &str,
) -> RuntimeSourceSurfaces {
RuntimeSourceSurfaces {
profile_memory: RuntimeTextSurface {
kind: "profile_memory",
path: PathBuf::from("/tmp/profile-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: profile.to_owned(),
migrated_from: None,
},
locality_memory: RuntimeTextSurface {
kind: "locality_memory",
path: PathBuf::from("/tmp/repo-memory.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: repo.to_owned(),
migrated_from: None,
},
pod_memory: missing_pod_memory_surface(),
branch_memory: missing_branch_memory_surface(),
clone_memory: missing_clone_memory_surface(),
execution_gates: missing_execution_gates_surface(),
handoff: RuntimeTextSurface {
kind: "handoff",
path: PathBuf::from("/tmp/handoff.md"),
status: RuntimeTextSurfaceStatus::Loaded,
content: handoff.to_owned(),
migrated_from: None,
},
}
}
#[test]
fn projection_digests_are_deterministic() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Rule one.")],
locality: vec![RuntimeMemoryEntry::narrative("Repo note.")],
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Determinism".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Check hashes.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: Vec::new(),
operational_guardrails: Vec::new(),
key_files: Vec::new(),
definition_of_done: Vec::new(),
},
};
let sources = make_test_sources("profile", "repo", "focus", "handoff");
let first =
compile_runtime_projection(&state, &sources, ProjectionTarget::Session, false).unwrap();
let second =
compile_runtime_projection(&state, &sources, ProjectionTarget::Session, false).unwrap();
let d1 = first.projection_digests.unwrap();
let d2 = second.projection_digests.unwrap();
assert_eq!(d1, d2);
}
#[test]
fn projection_digests_stable_when_filtered_input_changes() {
let state = RuntimeState {
memory: RuntimeMemoryState {
profile: vec![RuntimeMemoryEntry::narrative("Rule one.")],
locality: Vec::new(),
pod: Vec::new(),
branch: Vec::new(),
clone: Vec::new(),
},
handoff: RuntimeHandoffState {
title: "Next Session: Filtered".to_owned(),
immediate_actions: vec![RuntimeHandoffItem {
text: "Act now.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
completed_state: vec![RuntimeHandoffItem {
text: "Completed work.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
operational_guardrails: Vec::new(),
key_files: vec![RuntimeHandoffItem {
text: "`src/file.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
definition_of_done: vec![RuntimeHandoffItem {
text: "Tests pass.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
}],
},
};
let state_modified = RuntimeState {
handoff: RuntimeHandoffState {
completed_state: vec![
RuntimeHandoffItem {
text: "Completed work.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
RuntimeHandoffItem {
text: "Extra completed item.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
],
key_files: vec![
RuntimeHandoffItem {
text: "`src/file.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
RuntimeHandoffItem {
text: "`src/new_file.rs`".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
],
definition_of_done: vec![
RuntimeHandoffItem {
text: "Tests pass.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
RuntimeHandoffItem {
text: "Docs updated.".to_owned(),
lifecycle: RuntimeLifecycle::Active,
},
],
..state.handoff.clone()
},
..state.clone()
};
let sources = make_test_sources("profile", "repo", "focus", "handoff");
let original =
compile_runtime_projection(&state, &sources, ProjectionTarget::Session, false).unwrap();
let modified =
compile_runtime_projection(&state_modified, &sources, ProjectionTarget::Session, false)
.unwrap();
let d_original = original.projection_digests.unwrap();
let d_modified = modified.projection_digests.unwrap();
assert_eq!(
d_original, d_modified,
"session target filters completed_state, key_files, and definition_of_done — changing only those should not change projection digests"
);
}
#[test]
fn context_delta_returns_only_changed_surfaces() {
let previous = ProjectionDigests {
effective_memory: "aaa".to_owned(),
handoff: "ccc".to_owned(),
execution_gates: "ddd".to_owned(),
escalation: "eee".to_owned(),
recovery: "fff".to_owned(),
git_state: "ggg".to_owned(),
session_state: "hhh".to_owned(),
};
let current = ProjectionDigests {
effective_memory: "aaa".to_owned(),
handoff: "ccc_changed".to_owned(),
execution_gates: "ddd".to_owned(),
escalation: "eee".to_owned(),
recovery: "fff".to_owned(),
git_state: "ggg".to_owned(),
session_state: "hhh".to_owned(),
};
let delta =
compute_context_delta(&previous, ¤t, "fp_old", "fp_new").expect("delta present");
assert_eq!(delta.changed_surfaces.len(), 1);
assert_eq!(delta.changed_surfaces[0].name, "handoff");
assert_eq!(delta.previous_fingerprint, "fp_old");
assert_eq!(delta.current_fingerprint, "fp_new");
let no_delta = compute_context_delta(&previous, &previous, "fp", "fp");
assert!(no_delta.is_none());
}
#[test]
fn projection_digests_ignores_old_repo_focus_field() {
let old_json = r#"{"effective_memory":"aaa","repo_focus":"bbb","handoff":"ccc"}"#;
let digests: ProjectionDigests = serde_json::from_str(old_json)
.expect("old repo_focus field should deserialize as ignored legacy data");
assert_eq!(digests.effective_memory, "aaa");
assert_eq!(digests.handoff, "ccc");
let reserialized = serde_json::to_string(&digests).expect("serialize");
assert!(!reserialized.contains("repo_focus"));
assert!(!reserialized.contains("workflow_signal"));
}
#[test]
fn projection_digests_deserializes_legacy_minimal_shape() {
let old_json = r#"{"effective_memory":"aaa","handoff":"ccc"}"#;
let digests: ProjectionDigests = serde_json::from_str(old_json)
.expect("legacy digests should deserialize without workflow_signal");
assert_eq!(digests.effective_memory, "aaa");
assert_eq!(digests.handoff, "ccc");
}
#[test]
fn projection_digests_ignore_legacy_workflow_signal_field() {
let json = r#"{"effective_memory":"aaa","workflow_signal":"bbb","handoff":"ccc"}"#;
let digests: ProjectionDigests = serde_json::from_str(json).unwrap();
assert_eq!(digests.effective_memory, "aaa");
assert_eq!(digests.handoff, "ccc");
assert_eq!(digests.execution_gates, "");
assert_eq!(digests.escalation, "");
assert_eq!(digests.recovery, "");
assert_eq!(digests.git_state, "");
assert_eq!(digests.session_state, "");
}
#[test]
fn compute_extended_digests_hashes_all_surfaces() {
let base = ProjectionDigests {
effective_memory: "mem_hash".to_owned(),
handoff: "ho_hash".to_owned(),
execution_gates: String::new(),
escalation: String::new(),
recovery: String::new(),
git_state: String::new(),
session_state: String::new(),
};
let extended = compute_extended_digests(&base, "gates", "esc", "rec", "git", "sess");
assert_eq!(extended.effective_memory, "mem_hash");
assert_eq!(extended.handoff, "ho_hash");
assert_ne!(extended.execution_gates, "");
assert_ne!(extended.escalation, "");
assert_ne!(extended.recovery, "");
assert_ne!(extended.git_state, "");
assert_ne!(extended.session_state, "");
let extended2 = compute_extended_digests(&base, "gates", "esc", "rec", "git", "sess");
assert_eq!(extended.execution_gates, extended2.execution_gates);
}
#[test]
fn context_delta_skips_empty_extended_fields() {
let old = ProjectionDigests {
effective_memory: "aaa".to_owned(),
handoff: "ccc".to_owned(),
execution_gates: String::new(), escalation: String::new(),
recovery: String::new(),
git_state: String::new(),
session_state: String::new(),
};
let new = ProjectionDigests {
effective_memory: "aaa".to_owned(),
handoff: "ddd".to_owned(), execution_gates: "xxx".to_owned(),
escalation: "yyy".to_owned(),
recovery: "zzz".to_owned(),
git_state: "ggg".to_owned(),
session_state: "sss".to_owned(),
};
let delta = compute_context_delta(&old, &new, "fp1", "fp2");
assert!(delta.is_some());
let delta = delta.unwrap();
assert_eq!(delta.changed_surfaces.len(), 1);
assert_eq!(delta.changed_surfaces[0].name, "handoff");
}
}