use std::fs;
use std::path::Path;
use anyhow::{Context, bail};
use crate::adapters::descriptor::layers::{
Layer, check_user_layer_restrictions, default_config_root, discover_sources,
};
use crate::adapters::descriptor::{
HarnessDescriptor, finalize_descriptor, merge_descriptor_value, parse_descriptor_value, subst,
};
use crate::adapters::registry::{HarnessInfo, default_harness_name, harness_info};
use crate::core::Harness;
use crate::cli::args::{HarnessArgs, HarnessCommands};
const INIT_TEMPLATE: &str = include_str!("../../../harnesses/template.toml");
const INIT_NOTES_TEMPLATE: &str = include_str!("../../../harnesses/template-notes.md");
pub(crate) fn run_harness(args: HarnessArgs) -> anyhow::Result<()> {
match args.command {
HarnessCommands::Init {
name,
stdout,
force,
} => run_init_scaffold(&name, stdout, force),
HarnessCommands::List => run_list(),
HarnessCommands::Show { name } => run_show(&name),
HarnessCommands::Lint { target } => run_lint(&target),
}
}
fn run_init_scaffold(name: &str, stdout: bool, force: bool) -> anyhow::Result<()> {
let is_kebab = !name.is_empty()
&& name.split('-').all(|seg| {
!seg.is_empty()
&& seg
.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
});
if !is_kebab {
bail!(
"harness name {name:?} must be kebab-case (lowercase alphanumerics separated by \
single hyphens), e.g. cool-cli"
);
}
let rendered = subst(INIT_TEMPLATE, &[("label", name)]);
let source = format!("harness init {name} (rendered template)");
let value = parse_descriptor_value(&rendered, &source)?;
check_user_layer_restrictions(&value, &source)?;
finalize_descriptor(&value, &source)?;
if stdout {
print!("{rendered}");
return Ok(());
}
if let Some(info) = harness_info().find(|info| info.label == name) {
eprintln!(
"note: '{name}' is already registered ({}) — this file will overlay it \
field-by-field (docs/byoh.md \"Layering\"); pick a new name for a new harness, \
or start an overlay from `eval-magic harness show {name}`.",
layer_chain(&info)
);
}
let dir = Path::new(".eval-magic").join("harnesses");
let descriptor_path = dir.join(format!("{name}.toml"));
let notes_path = dir.join(format!("{name}-notes.md"));
if !force {
for path in [&descriptor_path, ¬es_path] {
if path.exists() {
bail!(
"{} already exists — pass --force to overwrite it",
path.display()
);
}
}
}
fs::create_dir_all(&dir).with_context(|| format!("cannot create {}", dir.display()))?;
fs::write(&descriptor_path, &rendered)
.with_context(|| format!("cannot write {}", descriptor_path.display()))?;
fs::write(¬es_path, subst(INIT_NOTES_TEMPLATE, &[("label", name)]))
.with_context(|| format!("cannot write {}", notes_path.display()))?;
println!(
"Scaffolded harness descriptor: {}",
descriptor_path.display()
);
println!("Scaffolded notes skeleton: {}", notes_path.display());
println!();
lint_file(&descriptor_path)?;
println!();
println!("Next:");
println!(" 1. Fill in verified values — follow the template's comments; never guess a flag");
println!(
" (record each value's source in {}).",
notes_path.display()
);
println!(
" 2. Re-lint after every edit: eval-magic harness lint {}",
descriptor_path.display()
);
println!(
" 3. Smoke eval: eval-magic run --harness {name} (dispatch, then ingest + finalize)"
);
println!(
" 4. Upstreaming the proven descriptor: docs/byoh.md \"Upstreaming your descriptor\"."
);
Ok(())
}
fn run_list() -> anyhow::Result<()> {
let default_name = default_harness_name();
let rows: Vec<(String, String, String)> = harness_info()
.map(|info| {
let name = if info.label == default_name {
format!("{} (default)", info.label)
} else {
info.label.to_string()
};
(
name,
layer_chain(&info),
declared_enhancements(info.descriptor),
)
})
.collect();
let name_width = rows.iter().map(|(n, _, _)| n.len()).max().unwrap_or(0);
let layer_width = rows.iter().map(|(_, l, _)| l.len()).max().unwrap_or(0);
for (name, layers, enhancements) in rows {
println!("{name:<name_width$} {layers:<layer_width$} {enhancements}");
}
Ok(())
}
fn run_show(name: &str) -> anyhow::Result<()> {
let Some(info) = harness_info().find(|info| info.label == name) else {
return Err(Harness::resolve(name)
.expect_err("name is absent from the registry")
.into());
};
println!("# {name} — resolved descriptor (after layer merging)");
println!("# sources:");
for (layer, path) in info.sources {
println!("# {path} ({})", layer.display_name());
}
println!();
print!("{}", toml::to_string(info.descriptor)?);
Ok(())
}
fn run_lint(target: &str) -> anyhow::Result<()> {
let looks_like_path = target.contains(std::path::MAIN_SEPARATOR)
|| target.ends_with(".toml")
|| Path::new(target).is_file();
if looks_like_path {
lint_file(Path::new(target))
} else {
lint_name(target)
}
}
fn lint_file(path: &Path) -> anyhow::Result<()> {
let display = path.display();
let toml_src = fs::read_to_string(path).with_context(|| format!("cannot read {display}"))?;
let mut failed = 0usize;
let value = match parse_descriptor_value(&toml_src, &display.to_string()) {
Ok(value) => {
println!("✓ TOML syntax + schema");
Some(value)
}
Err(e) => {
eprintln!("✗ {e}");
failed += 1;
None
}
};
if let Some(value) = &value {
match check_user_layer_restrictions(value, &display.to_string()) {
Ok(()) => println!("✓ user-layer restrictions ([guard] stays built-in-only)"),
Err(e) => {
eprintln!("✗ {e}");
failed += 1;
}
}
let label = value.get("label").and_then(serde_json::Value::as_str);
let target = label.and_then(|l| harness_info().find(|info| info.label == l));
let (merged, provenance) = match &target {
Some(info) => {
let mut merged = info.value.clone();
merge_descriptor_value(&mut merged, value.clone());
(
merged,
format!("{} + {display} (lint)", layer_provenance(info)),
)
}
None => (value.clone(), display.to_string()),
};
match finalize_descriptor(&merged, &provenance) {
Ok(_) => match &target {
Some(info) => println!("✓ cross-field invariants (merged onto {})", info.label),
None => println!("✓ cross-field invariants"),
},
Err(e) => {
eprintln!("✗ {e}");
failed += 1;
}
}
}
if failed > 0 {
bail!("descriptor lint failed for {display}: {failed} check(s) failed");
}
println!("Linted {display}: all checks passed.");
Ok(())
}
fn lint_name(name: &str) -> anyhow::Result<()> {
let project_root = std::env::current_dir().unwrap_or_default();
let (sources, io_warnings) =
discover_sources(default_config_root().as_deref(), &project_root, None)
.map_err(anyhow::Error::from)?;
let mut failed = io_warnings.len();
for warning in io_warnings {
eprintln!("✗ {warning}");
}
let mut chain: Option<(serde_json::Value, Vec<String>)> = None;
for source in sources {
let value = match parse_descriptor_value(&source.toml_src, &source.path) {
Ok(value) => value,
Err(e) => {
if source.layer != Layer::Embedded {
eprintln!("✗ {e}");
failed += 1;
}
continue;
}
};
if source.layer != Layer::Embedded
&& let Err(e) = check_user_layer_restrictions(&value, &source.path)
{
eprintln!("✗ {e}");
failed += 1;
continue;
}
if value.get("label").and_then(serde_json::Value::as_str) != Some(name) {
continue;
}
let step = format!("{} ({})", source.path, source.layer.display_name());
println!("✓ {step}: schema + user-layer checks");
match &mut chain {
None => chain = Some((value, vec![step])),
Some((base, steps)) => {
let mut merged = base.clone();
merge_descriptor_value(&mut merged, value);
steps.push(step);
let provenance = steps.join(" + ");
match finalize_descriptor(&merged, &provenance) {
Ok(_) => *base = merged,
Err(e) => {
eprintln!("✗ {e}");
failed += 1;
steps.pop();
}
}
}
}
}
match &chain {
Some((value, steps)) => {
let provenance = steps.join(" + ");
match finalize_descriptor(value, &provenance) {
Ok(_) => println!("✓ resolved descriptor: {provenance}"),
Err(e) => {
eprintln!("✗ {e}");
failed += 1;
}
}
}
None => match harness_info().find(|info| info.label == name) {
Some(info) => println!("✓ registered: {}", layer_provenance(&info)),
None if failed == 0 => {
return Err(Harness::resolve(name)
.expect_err("name is absent from every layer")
.into());
}
None => {}
},
}
if failed > 0 {
bail!(
"descriptor lint found {failed} failing check(s) across the discovered layers \
(see ✗ lines above; broken files are reported even when their label is not \
{name:?}, since a file that fails to parse has no readable label)"
);
}
println!("Linted {name}: all checks passed.");
Ok(())
}
fn layer_chain(info: &HarnessInfo) -> String {
info.sources
.iter()
.map(|(layer, _)| layer.display_name())
.collect::<Vec<_>>()
.join(" + ")
}
fn layer_provenance(info: &HarnessInfo) -> String {
info.sources
.iter()
.map(|(layer, path)| format!("{path} ({})", layer.display_name()))
.collect::<Vec<_>>()
.join(" + ")
}
fn declared_enhancements(descriptor: &HarnessDescriptor) -> String {
let mut list: Vec<&str> = Vec::new();
if descriptor.skills_dir.is_some() {
list.push("staging");
}
if descriptor.skills_block.is_some() {
list.push("skills-block");
}
if descriptor.transcript.is_some() {
list.push("transcript");
}
if descriptor.model.is_some() {
list.push("model-flag");
}
if descriptor.guard.is_some() {
list.push("guard");
}
if descriptor.shadow.is_some() {
list.push("shadow-preflight");
}
if !descriptor.dispatch.is_empty() {
list.push("dispatch-recipes");
}
if list.is_empty() {
"baseline".to_string()
} else {
list.join(", ")
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::adapters::descriptor::load_descriptor;
#[test]
fn rendered_template_passes_the_full_descriptor_pipeline() {
let rendered = subst(INIT_TEMPLATE, &[("label", "demo")]);
let value = parse_descriptor_value(&rendered, "template").expect("schema-clean");
check_user_layer_restrictions(&value, "template").expect("no guard data");
let descriptor = load_descriptor(&rendered, "template").expect("invariant-clean");
assert_eq!(descriptor.label, "demo");
assert!(descriptor.skills_dir.is_none());
assert!(descriptor.transcript.is_none());
assert!(descriptor.guard.is_none());
assert!(descriptor.dispatch.is_empty());
}
#[test]
fn template_substitutes_only_the_label_token() {
let rendered = subst(INIT_TEMPLATE, &[("label", "demo")]);
assert!(!rendered.contains("{label}"));
for survivor in ["{prefix}", "{model_arg}", "{name}", "{cwd}"] {
assert!(
rendered.contains(survivor),
"{survivor} should pass through subst"
);
}
}
#[test]
fn template_mentions_every_schema_field_and_capability_name() {
let schema: serde_json::Value = serde_json::from_str(include_str!(
"../../../schema/harness-descriptor.schema.json"
))
.expect("schema parses");
let properties = schema["properties"]
.as_object()
.expect("schema has properties");
for (field, spec) in properties {
assert!(
INIT_TEMPLATE.contains(field),
"template never mentions {field:?}"
);
if field == "guard" {
continue;
}
if let Some(nested) = spec["properties"].as_object() {
for (nested_field, nested_spec) in nested {
assert!(
INIT_TEMPLATE.contains(nested_field),
"template never mentions {field}.{nested_field}"
);
if let Some(values) = nested_spec["enum"].as_array() {
for value in values {
let value = value.as_str().expect("string enum");
assert!(
INIT_TEMPLATE.contains(value),
"template never mentions capability {field}.{nested_field} = \
{value:?}"
);
}
}
}
}
}
assert!(
INIT_TEMPLATE.contains("[guard]"),
"the guard restriction must be explained"
);
}
#[test]
fn fully_uncommented_template_is_a_coherent_descriptor() {
let rendered = subst(INIT_TEMPLATE, &[("label", "demo")]);
let uncommented: String = rendered
.lines()
.map(|line| line.strip_prefix("# ").unwrap_or(line))
.collect::<Vec<_>>()
.join("\n");
let value =
parse_descriptor_value(&uncommented, "uncommented template").expect("schema-clean");
check_user_layer_restrictions(&value, "uncommented template").expect("no guard data");
let descriptor =
load_descriptor(&uncommented, "uncommented template").expect("invariant-clean");
assert!(descriptor.skills_dir.is_some());
assert!(descriptor.transcript.is_some());
assert!(descriptor.model.is_some());
assert!(descriptor.skills_block.is_some());
assert!(descriptor.shadow.is_some());
assert!(!descriptor.dispatch.is_empty());
assert!(descriptor.guard.is_none());
}
}