bot-forge 1.0.2

Rust CLI for installing agent skills and developer tools from configurable forms.
Documentation
#!/usr/bin/env python3
"""Enforce current 1.0 module boundaries, contract removals, and hotspot ceilings."""

from __future__ import annotations

import json
import re
import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src"

# These are debt ceilings, not desired sizes. Reduce them when implementation moves to its domain.
LINE_CEILINGS = {
    "src/config/schema.rs": 4200,
    "src/execution/install.rs": 1900,
    "src/config/load.rs": 150,
    "src/cli/actions.rs": 900,
    "src/execution/command.rs": 925,
    "src/ui/progress.rs": 260,
    "src/execution/environment.rs": 600,
    # Public contract rustdoc counts toward this whole-file ceiling.
    "src/model.rs": 450,
    "src/model/output.rs": 180,
    "src/ui/mod.rs": 1750,
}

FORBIDDEN_DEPENDENCIES = {
    "src/config/": (
        "crate::cli",
        "crate::execution",
        "crate::planning",
        "crate::reporting",
        "crate::state",
        "crate::ui",
    ),
    "src/planning/": (
        "crate::backends",
        "crate::cli",
        "crate::diagnostics",
        "crate::execution",
        "crate::reporting",
        "crate::state",
        "crate::ui",
    ),
    "src/state/": (
        "crate::cli",
        "crate::execution",
        "crate::planning",
        "crate::reporting",
        "crate::telemetry",
        "crate::ui",
    ),
    "src/backends/": (
        "crate::execution",
        "crate::reporting",
        "crate::state",
        "crate::ui",
    ),
    "src/diagnostics/": ("crate::execution", "crate::reporting", "crate::ui"),
    "src/items/": ("crate::execution", "crate::reporting", "crate::ui"),
    "src/telemetry.rs": (
        "crate::execution",
        "crate::reporting",
        "crate::state",
        "crate::ui",
    ),
    "src/ui/": ("crate::execution", "crate::reporting"),
    "src/reporting/": ("crate::events", "crate::ui"),
    "src/execution/": ("crate::items", "crate::reporting"),
    "src/paths.rs": ("crate::model",),
    "src/fsutil.rs": ("crate::execution", "crate::reporting"),
}

REMOVED_PRODUCTION_CONTRACTS = (
    "rsenvforge",
    "schema_version",
    "install-crate",
    "install-skill",
)

# Application-only capabilities belong behind the library's CLI façade. Making one of these
# modules public recreates the binary/library visibility leak that the façade is intended to avoid.
PRIVATE_CRATE_MODULES = (
    "backends",
    "activation",
    "artifact",
    "cancellation",
    "diagnostics",
    "events",
    "fsutil",
    "items",
    "paths",
    "reporting",
    "redaction",
    "skills",
    "telemetry",
    "ui",
    "util",
)


def rust_files() -> list[Path]:
    return sorted(SRC.rglob("*.rs"))


def relative(path: Path) -> str:
    return path.relative_to(ROOT).as_posix()


def source(path: Path) -> str:
    return path.read_text(encoding="utf-8-sig")


def production_source(path: Path) -> str:
    """Exclude the isolated test module when checking production contracts."""
    return source(path).rsplit("#[cfg(test)]", 1)[0]


def count_lines(path: Path) -> int:
    return len(source(path).splitlines())


def main() -> int:
    failures: list[str] = []
    metrics: dict[str, object] = {}

    line_counts = {
        # Whole-file ceilings are intentionally simple and cannot be bypassed by placing a test
        # module before later production items.
        name: count_lines(ROOT / name)
        for name in LINE_CEILINGS
    }
    for name, count in line_counts.items():
        if count > LINE_CEILINGS[name]:
            failures.append(f"{name} has {count} lines; debt ceiling is {LINE_CEILINGS[name]}")
    metrics["hotspot_lines"] = line_counts

    boundary_violations: dict[str, list[str]] = {}
    for path in rust_files():
        name = relative(path)
        for prefix, dependencies in FORBIDDEN_DEPENDENCIES.items():
            if name.startswith(prefix):
                found = [item for item in dependencies if item in production_source(path)]
                if found:
                    boundary_violations[name] = found
                    failures.append(f"{name} crosses boundary via {', '.join(found)}")
    metrics["boundary_violations"] = boundary_violations

    removed_contract_hits: dict[str, list[str]] = {}
    for path in rust_files():
        hits = [item for item in REMOVED_PRODUCTION_CONTRACTS if item in production_source(path)]
        if hits:
            removed_contract_hits[relative(path)] = hits
            failures.append(f"{relative(path)} retains removed contract(s): {', '.join(hits)}")
    metrics["removed_contract_hits"] = removed_contract_hits

    lib_source = source(SRC / "lib.rs")
    public_application_modules = [
        module
        for module in PRIVATE_CRATE_MODULES
        if re.search(rf"^pub mod {re.escape(module)};", lib_source, re.MULTILINE)
    ]
    if public_application_modules:
        failures.append(
            "application-only crate modules are public: "
            + ", ".join(public_application_modules)
        )
    metrics["public_application_modules"] = public_application_modules

    production_lines = sum(count_lines(path) for path in rust_files())
    metrics["production_rust_lines"] = production_lines
    metrics["rust_files"] = len(rust_files())
    metrics["status"] = "failed" if failures else "passed"
    metrics["failures"] = failures
    print(json.dumps(metrics, ensure_ascii=False, indent=2, sort_keys=True))

    if failures:
        for failure in failures:
            print(f"architecture audit: {failure}", file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":
    raise SystemExit(main())