feat: scheduler prompt injection (T1.4 PR3a) #8

Merged
clawdie merged 1 commit from feat/t14-pr3a-scheduler-injection into main 2026-05-31 17:05:46 +02:00
4 changed files with 41 additions and 1 deletions

View file

@ -27,6 +27,7 @@ fn smoke_config() -> DaemonConfig {
max_context_tokens: 128_000,
max_uncompacted_turns: 20,
cost_mode: "smart".to_string(),
scheduler_prompt_injection: false,
}
}

View file

@ -43,6 +43,9 @@ pub struct DaemonConfig {
pub max_uncompacted_turns: usize,
/// Current cost mode (fast/smart/max).
pub cost_mode: String,
/// Inject session prompt context into spawned agent env (T1.4 PR3a).
/// Disabled by default — enable when prompt discipline is verified.
pub scheduler_prompt_injection: bool,
}
impl DaemonConfig {
@ -86,6 +89,8 @@ impl DaemonConfig {
max_context_tokens: env_parse("COLIBRI_MAX_CONTEXT_TOKENS").unwrap_or(128_000),
max_uncompacted_turns: env_parse("COLIBRI_MAX_UNCOMPACTED_TURNS").unwrap_or(20),
cost_mode: std::env::var("COLIBRI_COST_MODE").unwrap_or_else(|_| "smart".to_string()),
scheduler_prompt_injection: env_parse("COLIBRI_SCHEDULER_PROMPT_INJECTION")
.unwrap_or(false),
}
}
}

View file

@ -360,6 +360,7 @@ mod tests {
max_context_tokens: 128_000,
max_uncompacted_turns: 20,
cost_mode: "smart".to_string(),
scheduler_prompt_injection: true,
}
}

View file

@ -9,6 +9,8 @@
use std::time::SystemTime;
use std::collections::HashMap;
use colibri_glasspane::DEFAULT_STALL_AFTER;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::{UnixListener, UnixStream};
@ -310,11 +312,41 @@ async fn cmd_spawn_agent(
args,
provider,
model,
session_id,
session_id: session_id.clone(),
system_prompt,
..Default::default()
};
// T1.4 PR3a: inject session prompt context as env var when enabled
let mut extra_env = HashMap::new();
if state.config.scheduler_prompt_injection {
if let Some(ref sid) = session_id {
if let Some(session) = state.sessions.get(sid) {
let assembly = session.value().build_prompt_assembly().await;
let cost_mode =
crate::cost::CostMode::parse(&state.config.cost_mode).unwrap_or_default();
let _ = assembly; // trimmed context available for injection
let context_json =
serde_json::to_string(&assembly.to_messages()).unwrap_or_default();
extra_env.insert("COLIBRI_SESSION_CONTEXT".to_string(), context_json);
extra_env.insert(
"COLIBRI_COST_MODE".to_string(),
cost_mode.as_str().to_string(),
);
info!(
session_id = %sid,
context_bytes = assembly.total_bytes,
cost_mode = cost_mode.as_str(),
"injected session prompt context"
);
}
}
}
// Merge extra env into agent config
let mut agent_config = agent_config;
agent_config.env.extend(extra_env);
let spawner = Spawner::new(state.config.clone().into());
match spawner.spawn(agent_config).await {
Ok(handle) => {
@ -605,6 +637,7 @@ mod tests {
max_context_tokens: 128_000,
max_uncompacted_turns: 20,
cost_mode: "smart".to_string(),
scheduler_prompt_injection: true,
}
}