sniff-cli 0.1.4

An exhaustive LLM-backed slop finder for codebases
Documentation
#![allow(clippy::await_holding_lock)]

use super::verdicts::normalize_file_verdict;
use super::*;
use crate::config::{LLMConfig, ResolvedConfig, ThresholdsConfig};
use crate::types::FindingTier;
use std::env;
use std::io::{Read, Write};
use std::net::{Shutdown, TcpListener};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
use std::sync::{Arc, Mutex, OnceLock};
use std::thread;
use std::time::Duration;

static ENV_LOCK: OnceLock<Mutex<()>> = OnceLock::new();

fn cfg(endpoint: &str) -> ResolvedConfig {
    ResolvedConfig {
        thresholds: ThresholdsConfig::default(),
        ignore: vec![],
        generic_names: vec![],
        generic_file_names: vec![],
        model: "test-model".to_string(),
        llm: LLMConfig {
            system_context: String::new(),
            endpoint: endpoint.to_string(),
        },
    }
}

fn semanticize_method_response(request: &str, body: &str) -> String {
    if !(request.contains("semantic intent pass")
        || request.contains("adversarial semantic pass")
        || request.contains("final adjudicator"))
    {
        return body.to_string();
    }

    let Ok(mut envelope) = serde_json::from_str::<serde_json::Value>(body) else {
        return body.to_string();
    };
    let Some(content) = envelope
        .pointer("/choices/0/message/content")
        .and_then(serde_json::Value::as_str)
    else {
        return body.to_string();
    };
    let Ok(mut verdict) = serde_json::from_str::<serde_json::Value>(content) else {
        return body.to_string();
    };

    let tier = verdict
        .get("tier")
        .and_then(serde_json::Value::as_str)
        .unwrap_or("clean")
        .to_string();
    let reason = verdict
        .get("reason")
        .and_then(serde_json::Value::as_str)
        .unwrap_or("")
        .to_string();
    let lower_reason = reason.to_lowercase();
    let prompt_source = request
        .split_once("Method source:\\n---\\n")
        .and_then(|(_, rest)| rest.split_once("\\n---"))
        .map(|(source, _)| source.replace("\\n", "\n").replace("\\\"", "\""))
        .unwrap_or_default();
    let should_be_clean = tier != "clean"
        && (reason.trim().is_empty()
            || prompt_source.trim().is_empty()
            || lower_reason.contains("previous version")
            || lower_reason.contains("copy-paste")
            || lower_reason.contains("format string uses placeholder")
            || lower_reason.contains("type annotation mismatch"));
    if should_be_clean {
        verdict["smelly"] = serde_json::Value::Bool(false);
        verdict["tier"] = serde_json::Value::String("clean".to_string());
        verdict["pattern"] = serde_json::Value::String("none".to_string());
        verdict["intent"] = serde_json::Value::String(
            "The method performs the behavior represented by the test fixture.".to_string(),
        );
        verdict["necessity_check"] = serde_json::Value::String(
            "The semantic review found no supported slop claim.".to_string(),
        );
        verdict["reason"] = serde_json::Value::String(String::new());
        verdict["evidence"] = serde_json::json!([]);
    } else {
        verdict["pattern"] = serde_json::Value::String(if tier == "clean" {
            "none".to_string()
        } else {
            "unnecessarily_complicated".to_string()
        });
        verdict["intent"] = serde_json::Value::String(
            "The method performs the behavior represented by the test fixture.".to_string(),
        );
        verdict["necessity_check"] = serde_json::Value::String(
            "The semantic review considered whether the implementation is necessary.".to_string(),
        );

        if tier == "clean" {
            verdict["evidence"] = serde_json::json!([]);
        } else {
            let evidence = verdict
                .get("evidence")
                .and_then(serde_json::Value::as_str)
                .unwrap_or("");
            let start_line = request
                .split_once("absolute file line numbers from ")
                .and_then(|(_, rest)| rest.split_once(" through "))
                .and_then(|(start, _)| start.trim().parse::<usize>().ok())
                .unwrap_or(1);
            let quote_is_in_source =
                prompt_source.contains(evidence) && !evidence.trim().is_empty();
            let quote = if quote_is_in_source {
                evidence.to_string()
            } else {
                prompt_source
                    .lines()
                    .find(|line| !line.trim().is_empty())
                    .unwrap_or("return value")
                    .to_string()
            };
            let quote_start_line = if quote_is_in_source {
                prompt_source
                    .lines()
                    .position(|line| line.contains(evidence))
                    .map(|offset| start_line + offset)
                    .unwrap_or(start_line)
            } else {
                start_line
            };
            let quote_end_line = quote_start_line + quote.lines().count().saturating_sub(1);
            verdict["evidence"] = serde_json::json!([{
                "start_line": quote_start_line,
                "end_line": quote_end_line,
                "quote": quote
            }]);
        }
    }

    let Some(content_slot) = envelope.pointer_mut("/choices/0/message/content") else {
        return body.to_string();
    };
    *content_slot = serde_json::Value::String(verdict.to_string());
    envelope.to_string()
}

fn spawn_openai_style_server(body: &'static str) -> (String, Arc<AtomicUsize>) {
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = listener.local_addr().unwrap();
    let hits = Arc::new(AtomicUsize::new(0));
    let hits_clone = Arc::clone(&hits);
    let (ready_tx, ready_rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = ready_tx.send(());
        loop {
            let Ok((mut stream, _)) = listener.accept() else {
                return;
            };
            let mut buf = [0u8; 16384];
            let Ok(n) = stream.read(&mut buf) else {
                continue;
            };
            if n == 0 {
                continue;
            }
            hits_clone.fetch_add(1, Ordering::SeqCst);
            let request = String::from_utf8_lossy(&buf[..n]);
            let body = semanticize_method_response(&request, body);
            let response = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = stream.write_all(response.as_bytes());
            let _ = stream.flush();
            let _ = stream.shutdown(Shutdown::Both);
        }
    });
    let _ = ready_rx.recv();
    thread::sleep(Duration::from_millis(50));

    (format!("http://{}", addr), hits)
}

fn spawn_openai_style_server_sequence(bodies: Vec<&'static str>) -> (String, Arc<AtomicUsize>) {
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = listener.local_addr().unwrap();
    let hits = Arc::new(AtomicUsize::new(0));
    let hits_clone = Arc::clone(&hits);
    let (ready_tx, ready_rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = ready_tx.send(());
        let mut idx = 0usize;
        let mut last_body = bodies.last().copied().unwrap_or("");
        loop {
            let body = if idx < bodies.len() {
                let body = bodies[idx];
                idx += 1;
                last_body = body;
                body
            } else {
                last_body
            };
            loop {
                let Ok((mut stream, _)) = listener.accept() else {
                    return;
                };
                let mut buf = [0u8; 16384];
                let Ok(n) = stream.read(&mut buf) else {
                    continue;
                };
                if n == 0 {
                    continue;
                }
                hits_clone.fetch_add(1, Ordering::SeqCst);
                let request = String::from_utf8_lossy(&buf[..n]);
                let body = semanticize_method_response(&request, body);
                let response = format!(
                    "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                    body.len(),
                    body
                );
                let _ = stream.write_all(response.as_bytes());
                let _ = stream.flush();
                let _ = stream.shutdown(Shutdown::Both);
                break;
            }
        }
    });
    let _ = ready_rx.recv();

    (format!("http://{}", addr), hits)
}

fn spawn_openai_style_server_with_capture(
    body: &'static str,
) -> (String, Arc<AtomicUsize>, Arc<Mutex<String>>) {
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = listener.local_addr().unwrap();
    let hits = Arc::new(AtomicUsize::new(0));
    let hits_clone = Arc::clone(&hits);
    let captured = Arc::new(Mutex::new(String::new()));
    let captured_clone = Arc::clone(&captured);
    let (ready_tx, ready_rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = ready_tx.send(());
        loop {
            let Ok((mut stream, _)) = listener.accept() else {
                return;
            };
            let mut buf = [0u8; 16384];
            let Ok(n) = stream.read(&mut buf) else {
                continue;
            };
            if n == 0 {
                continue;
            }
            hits_clone.fetch_add(1, Ordering::SeqCst);
            if let Ok(mut slot) = captured_clone.lock() {
                *slot = String::from_utf8_lossy(&buf[..n]).to_string();
            }
            let request = String::from_utf8_lossy(&buf[..n]);
            let body = semanticize_method_response(&request, body);
            let response = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = stream.write_all(response.as_bytes());
            let _ = stream.flush();
            let _ = stream.shutdown(Shutdown::Both);
        }
    });
    let _ = ready_rx.recv();

    (format!("http://{}", addr), hits, captured)
}

fn spawn_http_status_server(status: u16, body: &'static str) -> (String, Arc<AtomicUsize>) {
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = listener.local_addr().unwrap();
    let hits = Arc::new(AtomicUsize::new(0));
    let hits_clone = Arc::clone(&hits);
    let (ready_tx, ready_rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = ready_tx.send(());
        loop {
            let Ok((mut stream, _)) = listener.accept() else {
                return;
            };
            let mut buf = [0u8; 16384];
            let Ok(n) = stream.read(&mut buf) else {
                continue;
            };
            if n == 0 {
                continue;
            }
            hits_clone.fetch_add(1, Ordering::SeqCst);
            let response = format!(
                "HTTP/1.1 {} ERROR\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                status,
                body.len(),
                body
            );
            let _ = stream.write_all(response.as_bytes());
            let _ = stream.flush();
            let _ = stream.shutdown(Shutdown::Both);
        }
    });
    let _ = ready_rx.recv();

    (format!("http://{}", addr), hits)
}

fn spawn_http_status_sequence_server(
    statuses: Vec<u16>,
    body: &'static str,
) -> (String, Arc<AtomicUsize>) {
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = listener.local_addr().unwrap();
    let hits = Arc::new(AtomicUsize::new(0));
    let hits_clone = Arc::clone(&hits);
    let (ready_tx, ready_rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = ready_tx.send(());
        let mut idx = 0usize;
        let mut last_status = statuses.last().copied().unwrap_or(500);
        loop {
            let status = if idx < statuses.len() {
                let status = statuses[idx];
                idx += 1;
                last_status = status;
                status
            } else {
                last_status
            };
            let Ok((mut stream, _)) = listener.accept() else {
                return;
            };
            let mut buf = [0u8; 16384];
            let Ok(n) = stream.read(&mut buf) else {
                continue;
            };
            if n == 0 {
                continue;
            }
            hits_clone.fetch_add(1, Ordering::SeqCst);
            let response = format!(
                "HTTP/1.1 {} ERROR\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                status,
                body.len(),
                body
            );
            let _ = stream.write_all(response.as_bytes());
            let _ = stream.flush();
            let _ = stream.shutdown(Shutdown::Both);
        }
    });
    let _ = ready_rx.recv();

    (format!("http://{}", addr), hits)
}

#[path = "analyzer/evidence.rs"]
mod evidence;
#[path = "analyzer/normalization.rs"]
mod normalization;
#[path = "analyzer/repository.rs"]
mod repository;
#[path = "analyzer/support.rs"]
mod support;
#[path = "analyzer/surfaces.rs"]
mod surfaces;
#[path = "analyzer/transport.rs"]
mod transport;