weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
//! Source-boundary contracts for Weir as a standalone dataflow crate.
//!
//! Weir may have consumer-shaped integration tests, but shipped source docs
//! and production modules must describe dataflow capabilities generically.

use std::fs;
use std::path::{Path, PathBuf};

const FORBIDDEN_CONSUMER_NAMES: &[&str] = &["surgec", "gossan", "keyhog", "warpscan", "pyrograph"];

#[test]
fn source_docs_are_consumer_neutral() {
    let root = Path::new(env!("CARGO_MANIFEST_DIR"));
    let mut files = Vec::new();
    collect_rust_sources(&root.join("src"), &mut files);
    files.sort();

    let mut violations = Vec::new();
    for file in files {
        let source = fs::read_to_string(&file)
            .unwrap_or_else(|error| panic!("{} must be readable: {error}", file.display()));
        for (line_index, line) in source.lines().enumerate() {
            let trimmed = line.trim_start();
            let is_doc_or_comment = trimmed.starts_with("//!")
                || trimmed.starts_with("///")
                || trimmed.starts_with("// ")
                || trimmed.starts_with("/*")
                || trimmed.starts_with('*');
            if !is_doc_or_comment {
                continue;
            }
            let lower = trimmed.to_ascii_lowercase();
            for forbidden in FORBIDDEN_CONSUMER_NAMES {
                if lower.contains(forbidden) {
                    violations.push(format!(
                        "{}:{} names downstream consumer `{}`",
                        file.strip_prefix(root).unwrap_or(&file).display(),
                        line_index + 1,
                        forbidden
                    ));
                }
            }
        }
    }

    assert!(
        violations.is_empty(),
        "Weir source docs must stay dataflow-generic; consumer-specific names belong in consumer integration tests/evidence:\n{}",
        violations.join("\n")
    );
}

fn collect_rust_sources(path: &Path, out: &mut Vec<PathBuf>) {
    if path.is_file() {
        if path.extension().is_some_and(|extension| extension == "rs") {
            out.push(path.to_path_buf());
        }
        return;
    }
    if !path.is_dir() {
        return;
    }
    for entry in fs::read_dir(path)
        .unwrap_or_else(|error| panic!("{} must be readable: {error}", path.display()))
    {
        let path = entry
            .unwrap_or_else(|error| panic!("source directory entry must be readable: {error}"))
            .path();
        collect_rust_sources(&path, out);
    }
}