Skip to main content

split_brain_harness/
lib.rs

1pub mod adaptor;
2pub mod audit;
3pub mod backends;
4pub mod capability;
5pub mod code_gen;
6pub mod config;
7pub use config::validate_config;
8pub mod context_packs;
9pub mod extractor;
10pub mod generative_forge;
11pub mod harness;
12pub mod input_validation;
13pub mod normalizer;
14pub mod policy;
15pub mod rag;
16pub mod regenerative_forge;
17pub mod reputation;
18#[cfg(feature = "serve")]
19pub mod serve;
20pub mod session_log;
21pub mod soul;
22pub mod static_analysis;
23pub mod tool_forge;
24pub mod tool_memory;
25pub mod transformer;
26pub mod types;
27pub mod verifier;
28pub mod wasm_forge;
29
30use anyhow::Result;
31use types::{Config, HarnessResult};
32
33/// Top-level convenience function. Loads soul + backend from config,
34/// runs the full two-stage pipeline, returns a HarnessResult.
35pub async fn analyze(input: &str, config: &Config) -> Result<HarnessResult> {
36    let loaded_soul = soul::load(Some(&config.soul_path))?;
37    let engine = backends::init_engine(config);
38
39    let t = if let Some(ref path) = config.context_path {
40        let mut corpus = rag::ContextCorpus::embedded();
41        match rag::ContextCorpus::load(path) {
42            Ok(extra) => corpus.merge(extra),
43            Err(e) => eprintln!("warning: could not load context path {path:?}: {e}"),
44        }
45        transformer::SplitBrainTransformer::with_corpus(
46            loaded_soul,
47            corpus,
48            transformer::TransformPolicy::default(),
49        )
50    } else {
51        transformer::SplitBrainTransformer::new(loaded_soul)
52    };
53
54    let h = harness::Harness::new_with_transformer(t, engine.as_ref(), config);
55    h.analyze(input).await
56}
57
58/// Build the augmented system prompt and payload for `input` without calling
59/// the model. Used by `--dump-prompt` to print and exit before any API call.
60pub fn prepare_prompt(input: &str, config: &Config) -> Result<(String, String)> {
61    let loaded_soul = soul::load(Some(&config.soul_path))?;
62    let selections = adaptor::select_packs_with_evidence(input);
63    let active_packs: Vec<&'static context_packs::ContextPack> =
64        selections.iter().map(|s| s.pack).collect();
65    Ok(adaptor::prepare(
66        &loaded_soul.logic_system_prompt,
67        input,
68        &active_packs,
69    ))
70}