use super::*;
fn write_skill(root: &std::path::Path, name: &str, desc: &str) {
let dir = root.join(name);
fs::create_dir_all(&dir).unwrap();
fs::write(
dir.join("SKILL.md"),
format!("---\nname: {name}\ndescription: {desc}\n---\nFull body of {name}.\n"),
)
.unwrap();
}
#[serial_test::serial(real_fs)]
#[test]
fn system_prompt_index_includes_discovered_skill_name_and_description() {
let tmp = tempfile::TempDir::new().unwrap();
write_skill(tmp.path(), "commit-style", "How this repo writes commits");
let block = skills_index_for_prompt(&[tmp.path().to_path_buf()]).expect("an index block");
assert!(block.contains("Available skills (call `use_skill` to load one):"));
assert!(block.contains("commit-style: How this repo writes commits"));
assert!(!block.contains("Full body of commit-style."));
}
#[serial_test::serial(real_fs)]
#[test]
fn system_prompt_index_carries_the_install_hint_when_no_skills() {
let tmp = tempfile::TempDir::new().unwrap();
let block =
skills_index_for_prompt(&[tmp.path().to_path_buf()]).expect("install hint survives");
assert!(block.contains("newt skills install"));
assert!(!block.contains("Available skills"));
}
#[serial_test::serial(real_fs)]
#[test]
fn system_prompt_index_unions_search_path_first_dir_wins() {
let a = tempfile::TempDir::new().unwrap();
let b = tempfile::TempDir::new().unwrap();
write_skill(a.path(), "commit-style", "newt copy");
write_skill(b.path(), "commit-style", "claude copy");
write_skill(b.path(), "judge", "scoring");
let block = skills_index_for_prompt(&[a.path().to_path_buf(), b.path().to_path_buf()])
.expect("an index block");
assert!(block.contains("commit-style: newt copy"));
assert!(!block.contains("claude copy"));
assert!(block.contains("judge: scoring"));
}
#[serial_test::serial(real_fs)]
#[test]
fn no_soul_provider_means_no_default_soul_2935() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let tmp = tempfile::TempDir::new().unwrap();
let memory = newt_core::MemoryManager::new();
let prompt = rebuild_system_prompt(tmp.path().to_str().unwrap(), &memory, None, "s", None);
let first_line = newt_core::DEFAULT_SOUL
.lines()
.find(|l| !l.is_empty())
.unwrap();
assert!(
!prompt.contains(first_line),
"the builder must not inject DEFAULT_SOUL on its own; got: {prompt:.200}"
);
assert!(
prompt.contains("Workspace: "),
"the rest of the prompt is intact"
);
}
#[serial_test::serial(real_fs)]
#[test]
fn system_prompt_names_the_per_session_plan_path() {
let tmp = tempfile::TempDir::new().unwrap();
let ws = tmp.path().to_str().unwrap();
let path_a = newt_core::session_plan_path("sess-aaaa");
let path_a = path_a.to_string_lossy();
let prompt_a =
build_system_prompt_with_persona(ws, newt_core::DEFAULT_SOUL, None, None, &path_a, None);
assert!(
prompt_a.contains(path_a.as_ref()),
"prompt must name the session plan path"
);
assert!(
prompt_a.contains("Plan before coding"),
"the plan instruction must still be present (now injected, not in DEFAULT_SOUL)"
);
let path_b = newt_core::session_plan_path("sess-bbbb");
let prompt_b = build_system_prompt_with_persona(
ws,
newt_core::DEFAULT_SOUL,
None,
None,
&path_b.to_string_lossy(),
None,
);
assert!(prompt_b.contains(&*path_b.to_string_lossy()));
assert!(
!prompt_b.contains(path_a.as_ref()),
"sessions must not share a path"
);
}
#[serial_test::serial(real_fs)]
#[test]
fn default_soul_no_longer_hardcodes_a_plan_path() {
assert!(!newt_core::DEFAULT_SOUL.contains("plan.md"));
let tmp = tempfile::TempDir::new().unwrap();
let prompt = build_system_prompt_with_persona(
tmp.path().to_str().unwrap(),
"You are a custom agent.",
None,
None,
".scratch/sessions/xyz/plan.md",
None,
);
assert!(prompt.contains("You are a custom agent."));
assert!(prompt.contains(".scratch/sessions/xyz/plan.md"));
}
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn registered_agents_provider_block_reaches_prompt() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let dir = tempfile::TempDir::new().unwrap();
std::fs::write(dir.path().join("AGENTS.md"), "Run just check before PRs.").unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::AgentsProvider::new(true, None));
let ctx = newt_core::SessionContext {
workspace: dir.path().to_string_lossy().into_owned(),
session_id: "s".into(),
};
memory.initialize_all(&ctx).await;
let prompt = rebuild_system_prompt(
dir.path().to_str().unwrap(),
&memory,
None,
"test-conversation",
None,
);
assert!(prompt.contains("# Project instructions"));
assert!(prompt.contains("Run just check before PRs."));
}
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn historical_notes_preserve_content_without_redefining_the_live_workspace() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let dir = tempfile::TempDir::new().unwrap();
let old_workspace = dir.path().join("previous-repository");
let workspace = dir.path().join("current-repository");
fs::create_dir_all(&old_workspace).unwrap();
fs::create_dir_all(&workspace).unwrap();
let note = format!(
"The workspace root is {} on branch previous-work; use the retired_git tool.",
old_workspace.display()
);
let notes_path = dir.path().join("NOTES.md");
let original_notes = format!("{note}\nยง\n");
fs::write(¬es_path, &original_notes).unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::NoteStore::new(¬es_path, 2200));
let ctx = newt_core::SessionContext {
workspace: workspace.to_string_lossy().into_owned(),
session_id: "current-session".into(),
};
memory.initialize_all(&ctx).await;
let prompt = rebuild_system_prompt(&ctx.workspace, &memory, None, &ctx.session_id, None);
assert_eq!(fs::read_to_string(¬es_path).unwrap(), original_notes);
assert_eq!(prompt.matches(¬e).count(), 1, "retain the note verbatim");
let note_position = prompt.find(¬e).unwrap();
let history_position = prompt
.find("Historical notes from prior sessions")
.expect("cross-session notes must be framed as historical context");
assert!(history_position < note_position);
assert!(prompt.contains("Workspace, branch, and tool availability may be stale"));
assert!(prompt.contains("do not redefine current runtime state"));
let live_workspace_position = prompt
.find(&format!("Workspace: {}", workspace.display()))
.expect("the prompt must identify the actual initialized workspace");
assert!(note_position < live_workspace_position);
let live_context = &prompt[live_workspace_position..];
assert!(live_context.contains("current runtime root"));
assert!(live_context.contains("Relative tool paths resolve here"));
assert!(live_context
.contains("run_command starts here unless its cwd or command selects another directory"));
assert!(
live_context.contains("Other requested paths remain governed by the session's permissions")
);
}
struct SkillRootSandbox {
vars: Vec<(&'static str, Option<std::ffi::OsString>)>,
cwd: std::path::PathBuf,
}
impl SkillRootSandbox {
fn enter(config_dir: &std::path::Path, cwd: &std::path::Path) -> Self {
let keys = [
"NEWT_CONFIG",
newt_core::config::NEWT_CONFIG_DIR_ENV,
"HOME",
];
let sandbox = Self {
vars: keys.iter().map(|k| (*k, std::env::var_os(k))).collect(),
cwd: std::env::current_dir().unwrap(),
};
unsafe {
std::env::remove_var("NEWT_CONFIG");
std::env::set_var(newt_core::config::NEWT_CONFIG_DIR_ENV, config_dir);
std::env::set_var("HOME", config_dir);
}
std::env::set_current_dir(cwd).unwrap();
sandbox
}
}
impl Drop for SkillRootSandbox {
fn drop(&mut self) {
let _ = std::env::set_current_dir(&self.cwd);
for (key, value) in &self.vars {
unsafe {
match value {
Some(v) => std::env::set_var(key, v),
None => std::env::remove_var(key),
}
}
}
}
}
#[ignore = "real-resource: weekly/release tier; pins cwd, HOME and NEWT_CONFIG_DIR"]
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn a_bundled_only_skill_is_indexed_and_loaded_by_use_skill() {
let root = tempfile::TempDir::new().unwrap();
let checkout = root.path().join("checkout");
write_skill(
&checkout.join(".newt").join("bundled-skills"),
"grounding-skill",
"Only in the bundled dir",
);
let nested = checkout.join("crate");
let config_dir = root.path().join("config");
fs::create_dir_all(&nested).unwrap();
fs::create_dir_all(&config_dir).unwrap();
let _sandbox = SkillRootSandbox::enter(&config_dir, &nested);
let ws = nested.to_str().unwrap();
let prompt =
build_system_prompt_with_persona(ws, newt_core::DEFAULT_SOUL, None, None, "plan.md", None);
assert!(
prompt.contains("grounding-skill: Only in the bundled dir"),
"the prompt index must list the bundled-only skill"
);
let body = newt_core::execute_tool(
"use_skill",
&serde_json::json!({ "name": "grounding-skill" }),
ws,
false,
200,
&newt_core::Caveats::top(),
&mut newt_core::NoMcp,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.await;
assert!(
body.contains("Full body of grounding-skill."),
"use_skill must load the copy the index listed, got: {body}"
);
}
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn provider_annotations_labeled_independently_doer_2937() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let dir = tempfile::TempDir::new().unwrap();
let ws = dir.path();
fs::write(ws.join("AGENTS.md"), "Use four spaces for indentation.").unwrap();
let notes_path = ws.join("NOTES.md");
fs::write(¬es_path, "user: prefers vi\nยง\n").unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::SoulProvider::new(None));
memory.add_provider(newt_core::AgentsProvider::new(true, None));
memory.add_provider(newt_core::NoteStore::new(¬es_path, 2200));
let ctx = newt_core::SessionContext {
workspace: ws.to_string_lossy().into_owned(),
session_id: "s".into(),
};
memory.initialize_all(&ctx).await;
let sink = newt_core::agentic::request_report::ReportSink::new();
let prompt = rebuild_system_prompt(
ws.to_str().unwrap(),
&memory,
None,
"sess-doer",
Some(&sink),
);
sink.arm_capture_next();
let _ = sink.observe_request(&[&prompt], None);
let report = sink.last_report().expect("report captured");
let labels: Vec<&str> = report.system[0]
.components
.iter()
.map(|c| c.label.as_str())
.collect();
assert!(
labels.contains(&"soul"),
"doer must have 'soul' label; got {labels:?}"
);
assert!(
labels.contains(&"agents"),
"'agents' provider must be labeled; got {labels:?}"
);
assert!(
labels.contains(&"note_store"),
"'note_store' provider must be labeled; got {labels:?}"
);
assert!(
labels.contains(&"workspace-header"),
"workspace-header must be labeled; got {labels:?}"
);
let ws_chars = report.system[0]
.components
.iter()
.find(|c| c.label == "workspace-header")
.expect("workspace-header component must exist")
.chars;
assert!(
ws_chars < 500,
"workspace-header chars ({ws_chars}) must be small โ not absorbing provider blocks"
);
}
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn provider_annotations_labeled_independently_coach_2937() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let dir = tempfile::TempDir::new().unwrap();
let ws = dir.path();
fs::write(ws.join("AGENTS.md"), "Always ask before acting.").unwrap();
let notes_path = ws.join("NOTES.md");
fs::write(¬es_path, "project: uses just check\nยง\n").unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::SoulProvider::new(None));
memory.add_provider(newt_core::AgentsProvider::new(true, None));
memory.add_provider(newt_core::NoteStore::new(¬es_path, 2200));
let ctx = newt_core::SessionContext {
workspace: ws.to_string_lossy().into_owned(),
session_id: "s".into(),
};
memory.initialize_all(&ctx).await;
let mut coach_persona = test_persona(
"coach",
"Give advice.",
std::path::PathBuf::from("/personas/coach.md"),
);
coach_persona.profile.altitude = Some(newt_core::Altitude::Coach);
let sink = newt_core::agentic::request_report::ReportSink::new();
let prompt = rebuild_system_prompt(
ws.to_str().unwrap(),
&memory,
Some(&coach_persona),
"sess-coach",
Some(&sink),
);
sink.arm_capture_next();
let _ = sink.observe_request(&[&prompt], None);
let report = sink.last_report().expect("report captured");
let labels: Vec<&str> = report.system[0]
.components
.iter()
.map(|c| c.label.as_str())
.collect();
assert!(
labels.contains(&"coach-soul"),
"coach must have 'coach-soul' label; got {labels:?}"
);
assert!(
labels.contains(&"agents"),
"'agents' provider must be labeled; got {labels:?}"
);
assert!(
labels.contains(&"note_store"),
"'note_store' provider must be labeled; got {labels:?}"
);
assert!(
labels.contains(&"workspace-header"),
"workspace-header must be labeled; got {labels:?}"
);
let ws_chars = report.system[0]
.components
.iter()
.find(|c| c.label == "workspace-header")
.expect("workspace-header component must exist")
.chars;
assert!(
ws_chars < 500,
"workspace-header chars ({ws_chars}) must not absorb provider blocks"
);
assert!(
prompt.contains("Always ask before acting"),
"agents content must reach prompt"
);
assert!(
prompt.contains("uses just check"),
"notes content must reach prompt"
);
}
#[serial_test::serial(real_fs)]
#[tokio::test]
async fn no_soul_provider_context_providers_still_annotated_2937() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let dir = tempfile::TempDir::new().unwrap();
let ws = dir.path();
fs::write(ws.join("AGENTS.md"), "Commit with clear messages.").unwrap();
let notes_path = ws.join("NOTES.md");
fs::write(¬es_path, "user: uses rg not grep\nยง\n").unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::AgentsProvider::new(true, None));
memory.add_provider(newt_core::NoteStore::new(¬es_path, 2200));
let ctx = newt_core::SessionContext {
workspace: ws.to_string_lossy().into_owned(),
session_id: "s".into(),
};
memory.initialize_all(&ctx).await;
let sink = newt_core::agentic::request_report::ReportSink::new();
let prompt = rebuild_system_prompt(
ws.to_str().unwrap(),
&memory,
None,
"sess-nosoul",
Some(&sink),
);
let first_line = newt_core::DEFAULT_SOUL
.lines()
.find(|l| !l.is_empty())
.unwrap();
assert!(
!prompt.contains(first_line),
"builder must not inject DEFAULT_SOUL; got: {prompt:.200}"
);
sink.arm_capture_next();
let _ = sink.observe_request(&[&prompt], None);
let report = sink.last_report().expect("report captured");
let labels: Vec<&str> = report.system[0]
.components
.iter()
.map(|c| c.label.as_str())
.collect();
assert!(
labels.contains(&"agents"),
"'agents' must be labeled even with no soul; got {labels:?}"
);
assert!(
labels.contains(&"note_store"),
"'note_store' must be labeled even with no soul; got {labels:?}"
);
assert!(
!labels.contains(&"soul"),
"no soul provider means no 'soul' label; got {labels:?}"
);
}
#[serial_test::serial(real_fs)]
#[test]
fn a_system_prompt_file_replaces_the_assembled_prompt_2938() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
let tmp = tempfile::TempDir::new().unwrap();
let workspace = tmp.path().to_str().unwrap();
let file = tmp.path().join("pruned.md");
let pruned = "Be brief.\n\n Keep this spacing.\n";
std::fs::write(&file, pruned).unwrap();
let mut memory = newt_core::MemoryManager::new();
memory.add_provider(newt_core::SoulProvider::new(None));
newt_core::process_env::set_var(newt_core::SYSTEM_PROMPT_FILE_ENV, file.to_str().unwrap());
let overridden = rebuild_system_prompt(workspace, &memory, None, "s", None);
newt_core::process_env::set_var(newt_core::SYSTEM_PROMPT_FILE_ENV, "");
let assembled = rebuild_system_prompt(workspace, &memory, None, "s", None);
newt_core::process_env::remove_var(newt_core::SYSTEM_PROMPT_FILE_ENV);
assert_eq!(overridden, pruned);
assert!(
assembled.contains("Workspace: "),
"unset, newt assembles its own: {assembled:.200}"
);
}