use std::path::{Path, PathBuf};
use std::sync::{Mutex, OnceLock};
use async_trait::async_trait;
use serde_json::json;
use supercode_harness::configfile::{resolve, ResolveOptions};
use supercode_harness::tools::{ToolContext, ToolRegistry};
use supercode_harness::{Agent, ChatMessage, ChatRequest, Config, Provider, Usage};
const NOTES_MARKER: &str = "NOTES-FILE-MARKER";
const SECRET_MARKER: &str = "SECRET-FILE-MARKER";
const ALWAYS_RULE_MARKER: &str = "ALWAYS-RULE-MARKER";
const SCOPED_RULE_MARKER: &str = "SCOPED-RULE-MARKER";
const STYLE_MARKER: &str = "CUSTOM-STYLE-MARKER";
const INJECTED_MARKER: &str = "INJECTED-OUTPUT-MARKER";
struct Estate {
project: PathBuf,
claude_home: PathBuf,
}
fn write(path: &Path, body: &str) {
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(path, body).unwrap();
}
fn estate() -> &'static Estate {
static ESTATE: OnceLock<Estate> = OnceLock::new();
ESTATE.get_or_init(|| {
let root = std::env::temp_dir().join(format!(
"supercode-bp5-prompt-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
let project = root.join("project");
let claude_home = root.join("claude-home");
let codex_home = root.join("codex-home");
let home = root.join("home");
std::fs::create_dir_all(project.join(".git")).unwrap();
std::fs::create_dir_all(codex_home.join("skills")).unwrap();
std::fs::create_dir_all(home.join(".agents").join("skills")).unwrap();
write(&project.join("notes.md"), &format!("{NOTES_MARKER}\nplans\n"));
write(&project.join(".env"), &format!("{SECRET_MARKER}\n"));
write(
&project.join(".codex").join("secrets.toml"),
&format!("{SECRET_MARKER}\n"),
);
write(
&project.join(".claude").join("rules").join("always.md"),
&format!("---\nname: house-style\n---\n\n{ALWAYS_RULE_MARKER}\nUse tabs.\n"),
);
write(
&project.join(".claude").join("rules").join("rust.md"),
&format!(
"---\nname: rust-rules\npaths:\n - \"src/**/*.rs\"\n---\n\n{SCOPED_RULE_MARKER}\nNo unwrap.\n"
),
);
write(&project.join("src").join("lib.rs"), "fn main() {}\n");
write(&project.join("README.md"), "readme\n");
write(
&project.join(".claude").join("commands").join("ship.md"),
"---\ndescription: Ship a release\narguments: version, channel\nargument-hint: <version> <channel>\n---\n\nShip $version to $channel.\nAll of it: $ARGUMENTS\nFirst positional: $1\n",
);
write(
&project
.join(".claude")
.join("commands")
.join("git")
.join("sync.md"),
"---\ndescription: Sync the branch\n---\n\nSync now.\n",
);
write(
&project.join(".claude").join("commands").join("status.md"),
&format!(
"---\ndescription: Report status\nallowed-tools:\n - Bash(echo:*)\n---\n\nHere it is: !`echo {INJECTED_MARKER}`\n"
),
);
write(
&project.join(".claude").join("commands").join("sneaky.md"),
&format!("---\ndescription: Not allowed to run anything\n---\n\nOutput: !`echo {INJECTED_MARKER}`\n"),
);
write(
&claude_home.join("output-styles").join("house.md"),
&format!("---\nname: house\ndescription: The house voice\n---\n\n{STYLE_MARKER}\nAnswer in one paragraph.\n"),
);
write(
&claude_home.join("output-styles").join("additive.md"),
&format!("---\nname: additive\nkeep-coding-instructions: true\n---\n\n{STYLE_MARKER}\nAlso explain.\n"),
);
write(
&project
.join(".agents")
.join("skills")
.join("report")
.join("SKILL.md"),
&format!("---\nname: report\ndescription: Report something\n---\n\nOutput: !`echo {INJECTED_MARKER}`\n"),
);
std::env::set_var("CLAUDE_CONFIG_DIR", &claude_home);
std::env::set_var("CODEX_HOME", &codex_home);
std::env::set_var("HOME", &home);
Estate {
project,
claude_home,
}
})
}
fn parity_config(preset: &str) -> Config {
let estate = estate();
let top = format!("extends = \"{preset}\"\n");
let mut resolved = resolve(&top, None, &ResolveOptions { strict: true })
.unwrap_or_else(|e| panic!("preset `{preset}` failed to resolve: {e}"));
resolved.config.cwd = estate.project.clone();
resolved.config
}
#[derive(Default)]
struct CapturingProvider {
last: Mutex<Option<ChatRequest>>,
}
#[async_trait]
impl Provider for CapturingProvider {
async fn complete(
&self,
req: &ChatRequest,
_on_delta: &(dyn for<'a> Fn(&'a str) + Send + Sync),
) -> supercode_harness::Result<(ChatMessage, Usage)> {
*self.last.lock().unwrap() = Some(req.clone());
Ok((ChatMessage::assistant("done"), Usage::default()))
}
}
fn agent_for(config: Config) -> Agent {
Agent::with_provider(config, Box::<CapturingProvider>::default())
}
fn system_prompt(agent: &Agent) -> String {
agent.history()[0].content.clone().unwrap_or_default()
}
fn last_user_text(agent: &Agent) -> String {
agent
.history()
.iter()
.rev()
.find(|m| m.role == supercode_harness::Role::User)
.and_then(|m| m.content.clone())
.unwrap_or_default()
}
#[tokio::test]
async fn cc_parity_at_mentions_inline_the_file_and_refuse_a_protected_one() {
let mut agent = agent_for(parity_config("cc-parity"));
agent.send("summarize @notes.md please").await.unwrap();
let sent = last_user_text(&agent);
assert!(sent.contains("summarize @notes.md please"), "{sent}");
assert!(sent.contains("[file: notes.md]"), "{sent}");
assert!(sent.contains(NOTES_MARKER), "the file's bytes: {sent}");
let mut agent = agent_for(parity_config("cc-parity"));
agent.send("check @.env").await.unwrap();
let sent = last_user_text(&agent);
assert!(
!sent.contains(SECRET_MARKER),
"a protected file's bytes reached the model: {sent}"
);
assert!(sent.contains("not attached"), "{sent}");
assert!(sent.contains("Deny"), "the reason is named: {sent}");
}
#[tokio::test]
async fn cx_parity_at_mentions_inline_the_file_and_refuse_a_protected_one() {
let mut agent = agent_for(parity_config("cx-parity"));
agent.send("summarize @notes.md").await.unwrap();
let sent = last_user_text(&agent);
assert!(sent.contains(NOTES_MARKER), "{sent}");
let mut agent = agent_for(parity_config("cx-parity"));
agent.send("check @.codex/secrets.toml").await.unwrap();
let sent = last_user_text(&agent);
assert!(!sent.contains(SECRET_MARKER), "{sent}");
assert!(sent.contains("not attached"), "{sent}");
}
#[tokio::test]
async fn a_mention_of_nothing_is_left_exactly_as_typed() {
let mut agent = agent_for(parity_config("cc-parity"));
agent
.send("mail me at @example.com about @nope.md")
.await
.unwrap();
let sent = last_user_text(&agent);
assert_eq!(sent, "mail me at @example.com about @nope.md");
}
#[tokio::test]
async fn cc_parity_discovers_command_files_as_slash_commands_with_an_argument_schema() {
let mut agent = agent_for(parity_config("cc-parity"));
let system = system_prompt(&agent);
assert!(
system.contains("- ship: Ship a release (arguments: <version> <channel>)"),
"{system}"
);
assert!(system.contains("- git:sync: Sync the branch"), "{system}");
agent.send("/ship 2.1.0 stable").await.unwrap();
let sent = last_user_text(&agent);
assert!(sent.contains("Ship 2.1.0 to stable."), "{sent}");
assert!(sent.contains("All of it: 2.1.0 stable"), "{sent}");
assert!(sent.contains("First positional: 2.1.0"), "{sent}");
assert!(!sent.contains("$ARGUMENTS"), "{sent}");
assert!(!sent.contains("description: Ship a release"), "{sent}");
}
#[tokio::test]
async fn cx_parity_has_no_markdown_command_files() {
let mut agent = agent_for(parity_config("cx-parity"));
agent.send("/ship 2.1.0 stable").await.unwrap();
assert_eq!(last_user_text(&agent), "/ship 2.1.0 stable");
}
#[tokio::test]
async fn cc_parity_runs_a_pre_approved_shell_injection_and_refuses_an_unapproved_one() {
let mut agent = agent_for(parity_config("cc-parity"));
agent.send("/status").await.unwrap();
let sent = last_user_text(&agent);
assert!(
sent.contains(&format!("Here it is: {INJECTED_MARKER}")),
"the body's own `allowed-tools` pre-approved `echo`: {sent}"
);
assert!(!sent.contains("!`echo"), "the token was consumed: {sent}");
let mut agent = agent_for(parity_config("cc-parity"));
agent.send("/sneaky").await.unwrap();
let sent = last_user_text(&agent);
assert!(
!sent.contains(&format!("Output: {INJECTED_MARKER}")),
"an unapproved command ran: {sent}"
);
assert!(sent.contains("was not run"), "{sent}");
assert!(
sent.contains("Ask"),
"the engine's verdict is named: {sent}"
);
}
#[tokio::test]
async fn the_skill_tool_expands_a_body_exactly_as_the_slash_door_does() {
let config = parity_config("cc-parity");
let registry = ToolRegistry::from_config(&config);
let tool = registry.get("skill").expect("cc-parity registers `skill`");
let ctx = ToolContext::new(config.cwd.clone());
let out = tool
.execute(json!({ "name": "status" }), &ctx)
.await
.unwrap();
assert!(out.contains(INJECTED_MARKER), "{out}");
let out = tool
.execute(json!({ "name": "sneaky" }), &ctx)
.await
.unwrap();
assert!(out.contains("was not run"), "{out}");
}
#[tokio::test]
async fn cx_parity_never_executes_a_body_s_shell_token() {
let config = parity_config("cx-parity");
assert!(!config.skills_shell_injection);
let mut agent = agent_for(config);
agent.send("run $report now").await.unwrap();
let sent = last_user_text(&agent);
assert!(sent.contains("!`echo"), "the token must be literal: {sent}");
assert!(
!sent.contains(&format!("Output: {INJECTED_MARKER}")),
"cx-parity executed a body's shell token: {sent}"
);
}
fn styled(preset: &str, style: &str) -> Config {
let mut config = parity_config(preset);
config.output_style = style.into();
config
}
#[test]
fn each_preset_pins_its_harness_s_own_neutral_style_and_swaps_to_a_named_one() {
let config = parity_config("cc-parity");
assert_eq!(config.output_style, "default");
let base = config.system_prompt.clone();
let neutral = system_prompt(&agent_for(config));
assert!(!neutral.contains("# Output style"), "{neutral}");
let system = system_prompt(&agent_for(styled("cc-parity", "explanatory")));
assert!(system.contains("# Output style: explanatory"), "{system}");
assert!(system.contains("Explain as you go"), "{system}");
assert!(system.contains(&base), "{system}");
let cx = parity_config("cx-parity");
assert_eq!(cx.output_style, "none");
assert!(!system_prompt(&agent_for(cx)).contains("# Output style"));
let system = system_prompt(&agent_for(styled("cx-parity", "friendly")));
assert!(system.contains("# Output style: friendly"), "{system}");
}
#[test]
fn a_user_authored_style_file_is_read_from_the_harness_s_own_root() {
let estate = estate();
assert!(estate.claude_home.join("output-styles").is_dir());
let base = parity_config("cc-parity").system_prompt;
let system = system_prompt(&agent_for(styled("cc-parity", "house")));
assert!(system.contains(STYLE_MARKER), "{system}");
assert!(
!system.contains(&base),
"a custom style without `keep-coding-instructions` must replace the base: {system}"
);
let system = system_prompt(&agent_for(styled("cc-parity", "additive")));
assert!(system.contains(STYLE_MARKER), "{system}");
assert!(system.contains(&base), "{system}");
}
#[tokio::test]
async fn cc_parity_loads_unscoped_rules_at_startup_and_scoped_ones_only_on_a_match() {
let config = parity_config("cc-parity");
assert!(config.path_rules);
let agent = agent_for(parity_config("cc-parity"));
let system = system_prompt(&agent);
assert!(system.contains("[rule: house-style]"), "{system}");
assert!(system.contains(ALWAYS_RULE_MARKER), "{system}");
assert!(
!system.contains(SCOPED_RULE_MARKER),
"a `paths:`-scoped rule must not be loaded until something matches: {system}"
);
let registry = ToolRegistry::from_config(&config);
let read = registry.get("read_file").unwrap();
let mut ctx = ToolContext::new(config.cwd.clone());
ctx.path_rules = std::sync::Arc::new(supercode_harness::path_rules::load(&config));
let untouched = read
.execute(json!({ "path": "README.md" }), &ctx)
.await
.unwrap();
assert!(!untouched.contains(SCOPED_RULE_MARKER), "{untouched}");
let matched = read
.execute(json!({ "path": "src/lib.rs" }), &ctx)
.await
.unwrap();
assert!(matched.contains("[rule: rust-rules]"), "{matched}");
assert!(matched.contains(SCOPED_RULE_MARKER), "{matched}");
let again = read
.execute(json!({ "path": "src/lib.rs" }), &ctx)
.await
.unwrap();
assert!(
!again.contains(SCOPED_RULE_MARKER),
"a rule is injected once per conversation: {again}"
);
}
#[test]
fn cx_parity_reads_no_rule_directory_at_all() {
let config = parity_config("cx-parity");
assert!(!config.path_rules);
assert!(supercode_harness::path_rules::load(&config).is_empty());
let system = system_prompt(&agent_for(config));
assert!(!system.contains(ALWAYS_RULE_MARKER), "{system}");
}
fn on_model(preset: &str, model: &str) -> Config {
let mut config = parity_config(preset);
config.model = model.into();
config
}
#[test]
fn cx_parity_selects_the_base_prompt_per_model_family_and_re_selects_on_a_switch() {
let config = parity_config("cx-parity");
assert!(
!config.model_family_prompts.is_empty(),
"cx-parity must carry `capabilities.model_catalog.base_prompts`"
);
let system = system_prompt(&agent_for(on_model("cx-parity", "openai/gpt-5.2-codex")));
assert!(
system.contains("*** Begin Patch"),
"the codex family is taught the apply_patch envelope: {system}"
);
let system = system_prompt(&agent_for(on_model("cx-parity", "openai/gpt-5.1")));
assert!(
system.contains("You are a coding agent running in a terminal."),
"{system}"
);
assert!(
!system.contains("*** Begin Patch"),
"a general gpt-5 family must not get the apply_patch tutorial: {system}"
);
let other = on_model("cx-parity", "anthropic/claude-opus-4-8");
let expected = other.system_prompt.clone();
let agent = agent_for(other);
assert_eq!(agent.base_prompt(), expected);
let mut agent = agent_for(on_model("cx-parity", "openai/gpt-5.1"));
assert!(!system_prompt(&agent).contains("*** Begin Patch"));
agent.set_model("openai/gpt-5.2-codex");
assert!(
system_prompt(&agent).contains("*** Begin Patch"),
"the base prompt must follow the model: {}",
system_prompt(&agent)
);
}
#[test]
fn cc_parity_has_no_family_table_and_keeps_its_single_base_prompt() {
let config = parity_config("cc-parity");
assert!(config.model_family_prompts.is_empty());
let expected = config.system_prompt.clone();
let agent = agent_for(config);
assert_eq!(agent.base_prompt(), expected);
}
#[tokio::test]
async fn model_input_renders_the_request_the_loop_would_send() {
let config = parity_config("cx-parity");
let model = config.model.clone();
let base = config.system_prompt.clone();
let mut agent = agent_for(config);
let req = agent.model_input_for("check @notes.md").await;
let rendered = Agent::render_model_input(&req);
assert_eq!(rendered["model"], json!(model));
let messages = rendered["messages"].as_array().unwrap();
assert_eq!(messages[0]["role"], "system");
assert!(messages[0]["content"].as_str().unwrap().contains(&base));
let last = messages.last().unwrap();
assert_eq!(last["role"], "user");
assert!(last["content"].as_str().unwrap().contains(NOTES_MARKER));
let tools: Vec<String> = rendered["tools"]
.as_array()
.unwrap()
.iter()
.map(|t| t["name"].as_str().unwrap().to_string())
.collect();
assert!(tools.contains(&"apply_patch".to_string()), "{tools:?}");
assert!(tools.contains(&"bash".to_string()), "{tools:?}");
assert!(
!tools.contains(&"read_file".to_string()),
"cx-parity has no read_file tool: {tools:?}"
);
assert!(!agent.request_issued());
}
#[tokio::test]
async fn the_rendered_input_is_the_one_the_provider_receives() {
let provider = std::sync::Arc::new(CapturingProvider::default());
let mut agent = Agent::with_provider(
parity_config("cc-parity"),
Box::new(SharedProvider(provider.clone())),
);
let rendered = Agent::render_model_input(&agent.model_input_for("hello there").await);
assert!(
provider.last.lock().unwrap().is_none(),
"rendering must not issue a request"
);
agent.send("hello there").await.unwrap();
let sent = provider.last.lock().unwrap().clone().expect("the turn ran");
let actual = Agent::render_model_input(&sent);
assert_eq!(
rendered["messages"][0]["content"], actual["messages"][0]["content"],
"the rendered system prompt is the one that went on the wire"
);
assert_eq!(rendered["tools"], actual["tools"]);
assert_eq!(rendered["model"], actual["model"]);
assert!(actual["messages"]
.as_array()
.unwrap()
.iter()
.any(|m| m["content"].as_str() == Some("hello there")));
}
struct SharedProvider(std::sync::Arc<CapturingProvider>);
#[async_trait]
impl Provider for SharedProvider {
async fn complete(
&self,
req: &ChatRequest,
on_delta: &(dyn for<'a> Fn(&'a str) + Send + Sync),
) -> supercode_harness::Result<(ChatMessage, Usage)> {
self.0.complete(req, on_delta).await
}
}