#multi-agent #schema #module-map #codebase-analysis

modmap

Universal module map schema for codebase structure representation

2 stable releases

Uses new Rust 2024

new 1.1.0 Feb 1, 2026
1.0.0 Jan 29, 2026

#372 in Data structures

MIT license

90KB
2K SLoC

modmap

Universal Module Map Schema for Codebase Structure Representation

CI Crates.io Docs.rs Rust License

English | 한국어


Overview

modmap is a language-agnostic schema library for representing codebase structure. It provides standardized types for describing modules, dependencies, conventions, and known issues across any programming language or framework.

Use Cases

  • Multi-agent systems: Define domain boundaries for agent coordination
  • Code analysis tools: Structured output format for codebase analyzers
  • Documentation generators: Machine-readable module descriptions
  • CI/CD pipelines: Automated codebase structure validation

Installation

[dependencies]
modmap = "1.0"

Quick Start

Creating a Module Map

use modmap::{
    GeneratorInfo, ModuleMap, ModuleGroup, ProjectMetadata,
    TechStack, Module, ModuleMetrics, ModuleDependency,
};

// Define project metadata
let project = ProjectMetadata::new("my-project", TechStack::new("rust").with_version("1.92"))
    .with_description("Example project")
    .with_total_files(50);

// Define modules
let modules = vec![
    Module {
        id: "auth".into(),
        name: "auth".into(),
        paths: vec!["src/auth/".into()],
        key_files: vec!["src/auth/mod.rs".into()],
        dependencies: vec![ModuleDependency::runtime("db")],
        dependents: vec!["api".into()],
        responsibility: "User authentication and session management".into(),
        primary_language: "rust".into(),
        metrics: ModuleMetrics::new(0.85, 0.9, 0.3),
        conventions: vec![],
        known_issues: vec![],
        evidence: vec![],
    },
];

// Create module map
let generator = GeneratorInfo::new("my-analyzer", "1.0.0");
let map = ModuleMap::new(generator, project, modules, vec![]);

// Serialize to JSON
let json = map.to_json()?;

Loading with Version Validation

use modmap::SchemaRegistry;

let registry = SchemaRegistry::new();
let map = registry.load_module_map(&json_string)?;

println!("Project: {}", map.project.name);
println!("Modules: {}", map.modules.len());

Schema Structure

Root Schema

ModuleMap
├── schema_version: "1.0.0"
├── generator: GeneratorInfo
├── project: ProjectMetadata
│   ├── name, description, repository
│   ├── project_type: Application | Library | Service | Cli
│   ├── workspace: WorkspaceInfo
│   ├── tech_stack: TechStack
│   ├── languages: Vec<DetectedLanguage>
│   └── commands: ProjectCommands
├── modules: Vec<Module>
├── groups: Vec<ModuleGroup>
├── dependency_graph: Option<DependencyGraph>
└── generated_at: DateTime<Utc>

Module

pub struct Module {
    pub id: String,
    pub name: String,
    pub paths: Vec<String>,
    pub key_files: Vec<String>,
    pub dependencies: Vec<ModuleDependency>,
    pub dependents: Vec<String>,
    pub responsibility: String,
    pub primary_language: String,
    pub metrics: ModuleMetrics,        // Flattened in JSON
    pub conventions: Vec<Convention>,
    pub known_issues: Vec<KnownIssue>,
    pub evidence: Vec<EvidenceLocation>,
}

Module Metrics

let metrics = ModuleMetrics::new(
    0.85,  // coverage_ratio
    0.9,   // value_score
    0.3,   // risk_score
);

// Priority calculation: value * 0.6 + risk * 0.4
let priority = metrics.priority_score();  // 0.66

Type Reference

Enums

Type Variants
WorkspaceType SinglePackage, Monorepo, Microservices, MultiPackage
ProjectType Application, Library, Service, Cli
DependencyType Runtime, Build, Test, Optional
IssueSeverity Critical, High, Medium, Low
IssueCategory Security, Performance, Correctness, Maintainability, Concurrency, Compatibility

Dependency Factory Methods

ModuleDependency::new("module-id")       // Default (Runtime)
ModuleDependency::runtime("database")    // Runtime dependency
ModuleDependency::build("codegen")       // Build-time dependency
ModuleDependency::test("fixtures")       // Test dependency
ModuleDependency::optional("cache")      // Optional dependency

Convention & Known Issue

use modmap::{Convention, KnownIssue, IssueSeverity, IssueCategory, EvidenceLocation};

let convention = Convention::new("error-handling", "Use ? operator for propagation")
    .with_rationale("Rust idiom for error handling")
    .with_evidence(vec![EvidenceLocation::new("src/lib.rs", 42)]);

let issue = KnownIssue::new(
    "race-condition",
    "Race condition in session refresh",
    IssueSeverity::High,
    IssueCategory::Concurrency,
)
.with_prevention("Use atomic CAS operations")
.with_evidence(vec![EvidenceLocation::new_range("src/session.rs", 128, 145)]);

Tech Stack

use modmap::{TechStack, FrameworkInfo, LibraryInfo};

let stack = TechStack::new("rust")
    .with_version("1.92")
    .with_framework(FrameworkInfo::new("tokio", "async runtime").with_version("1.0"))
    .with_build_tool("cargo")
    .with_test_framework("built-in")
    .with_library(LibraryInfo::new("serde", "serialization"));

Evidence Location

use modmap::EvidenceLocation;

let single = EvidenceLocation::new("src/main.rs", 42);
single.to_reference()  // "src/main.rs:42"

let range = EvidenceLocation::new_range("src/lib.rs", 10, 20);
range.to_reference()  // "src/lib.rs:10-20"

Module Groups

Group related modules with boundary rules:

use modmap::ModuleGroup;

let group = ModuleGroup::new("core", "Core Domain", vec!["auth".into(), "db".into()])
    .with_responsibility("Core business logic")
    .with_boundary_rules(vec!["No direct CLI dependencies".into()]);

Dependency Graph

Optional architecture layer representation:

use modmap::{DependencyGraph, DependencyEdge, ArchitectureLayer, DependencyType};

let graph = DependencyGraph {
    edges: vec![
        DependencyEdge {
            from: "api".into(),
            to: "auth".into(),
            edge_type: DependencyType::Runtime,
        },
    ],
    layers: vec![
        ArchitectureLayer {
            name: "presentation".into(),
            modules: vec!["cli".into(), "api".into()],
        },
        ArchitectureLayer {
            name: "domain".into(),
            modules: vec!["auth".into(), "db".into()],
        },
    ],
};

let map = ModuleMap::new(generator, project, modules, groups)
    .with_dependency_graph(graph);

Version Compatibility

Schema uses SemVer. The SchemaRegistry validates major version compatibility:

use modmap::{SchemaRegistry, SchemaError};

let registry = SchemaRegistry::new();

// Current version
println!("Schema version: {}", registry.version());  // 1.x.x

// Load and validate
match registry.load_module_map(&json) {
    Ok(map) => println!("Loaded: {}", map.project.name),
    Err(SchemaError::IncompatibleVersion { found, minimum }) => {
        eprintln!("Version {found} incompatible, requires {minimum}");
    }
    Err(e) => eprintln!("Error: {e}"),
}

JSON Schema

All types derive schemars::JsonSchema for JSON Schema generation:

use schemars::schema_for;
use modmap::ModuleMap;

let schema = schema_for!(ModuleMap);
println!("{}", serde_json::to_string_pretty(&schema)?);

Serialization

Optimized serde attributes for clean JSON output:

  • #[serde(default)] - Default values on deserialization
  • #[serde(skip_serializing_if = "Vec::is_empty")] - Omit empty collections
  • #[serde(flatten)] - Flatten ModuleMetrics into Module

License

MIT

Dependencies

~1.8–3MB
~55K SLoC