# AGENTS.md
This file provides guidance to AI code assistants when working with code in this repository.
## Project Overview
mmdflux is a Rust CLI tool and library that parses Mermaid diagrams and renders them as text (Unicode/ASCII), SVG, or MMDS JSON. Supported diagram types: flowchart, class, sequence. It converts Mermaid syntax into terminal-friendly visualizations using Unicode box-drawing characters, with support for multiple layout directions (TD, BT, LR, RL), node shapes, edge styles, subgraphs with direction overrides, and structured JSON output (MMDS format).
## Commit Conventions
This project uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), enforced by [cocogitto](https://docs.cocogitto.io/) via a `commit-msg` git hook.
Format: `<type>(<optional scope>): <subject>`
Types: `feat`, `fix`, `perf`, `revert`, `docs`, `test`, `build`, `ci`, `refactor`, `chore`, `style`
Scopes: `wasm`, `xtask`, `web`, `mmds-core`, `mmds-excalidraw`, `mmds-tldraw` (match monorepo packages). Omit scope for changes to the root `mmdflux` crate.
Rules:
- Header must be 100 characters or fewer
- Subject must start with a lowercase letter
- Subject must not end with a period
- Use imperative mood ("add feature" not "added feature")
For non-trivial changes, include a body after a blank line explaining **what** changed and **why**. A one-liner is fine for truly simple changes (typo fixes, version bumps), but multi-file changes, bug fixes, and new features should have a body.
Use `cog check` to validate commit history and `cog changelog` to preview changelog output. Use `git commit` (not `cog commit`) for creating commits — the commit-msg hook handles validation automatically.
## Branch Conventions
This project uses [Conventional Branch](https://conventional-branch.github.io/), enforced by a `pre-push` git hook.
Format: `<type>/<description>`
Types: `feat/`, `fix/`, `hotfix/`, `release/`, `chore/`
Rules:
- Use lowercase letters, numbers, and hyphens only (no underscores or spaces)
- Include issue numbers when applicable (e.g., `feat/issue-42-add-svg-export`)
- Keep descriptions concise (e.g., `fix/lr-routing-regression`)
## Issue and PR Workflow
When fixing a GitHub issue:
1. Read the issue and comments: `gh issue view <N> --comments`
2. Create a conventional branch: `fix/description` or `feat/description`
3. Keep PRs as a **single commit** — use `git commit --amend` and `git push --force-with-lease` when iterating
4. Reference the issue in the commit body: `Closes #N`
5. Post findings back to the issue with `gh issue comment <N>` when investigation reveals useful context
## Common Commands
Use `just` (see `Justfile`) for day-to-day work. Tests use `cargo-nextest` for parallel execution.
```bash
just test # Run all tests (nextest, parallel)
just test-file integration # Run a specific test file
just test -E 'test(test_name)' # Run a specific test (nextest filter)
just lint # clippy + fmt check
just check # lint + test + architecture
just build # Debug build
just release # Release build
just architecture-host # Host a semantic architecture lint server
just architecture-check # Run the archnitecture linter
just run diagram.mmd # Run the CLI
just fmt # Format code
# Run CLI directly
cargo run -- diagram.mmd
cargo run -- --debug diagram.mmd
cargo run -- --ascii diagram.mmd
echo 'graph LR\nA-->B' | cargo run
```
## Architecture
See `docs/architecture/dependency-rules.md` for the authoritative module ownership rules and public contract tiers. The repo-owned architecture gate is `cargo xtask architecture check` or `just architecture-check`. Semantic module boundaries are enforced from `boundaries.toml` (override with `SEMANTIC_BOUNDARIES_CONFIG`); run `cargo xtask architecture check` or `just architecture-check` for the semantic dependency check.
When editing imports, top-level wiring, or ownership boundaries, run
`cargo xtask architecture check` before finishing. During larger boundary
refactors, keep `just architecture-host` running in a separate terminal.
Inspection commands:
- `just architecture-graph` — print dependency graph as Mermaid
- `just architecture-explain --edge <source> <target>` — inspect a specific edge
- `just architecture-explain --boundary <name>` — inspect a boundary
Pipeline: **Frontend → Diagrams → Engine → Render**
```
Input Text → frontends.rs (detect frontend: Mermaid or MMDS)
→ mermaid/ (parse to AST) → diagrams/ (compile to IR, build payload)
→ runtime/ (orchestrate: registry → engine → render dispatch)
→ engines/ (solve graph layout → GraphGeometry)
→ render/ (emit Text/SVG/MMDS output)
```
### Public Contract Tiers
1. **Runtime facade**: `render_diagram`, `detect_diagram`, `validate_diagram` + `RenderConfig`, `OutputFormat`, `RenderError` re-exported from `lib.rs`
2. **Low-level API**: `builtins`, `registry`, `payload`, `graph`, `timeline`, `mmds` for adapter-oriented workflows
3. **Internal implementation**: `diagrams`, `engines`, `render`, `mermaid` — documented for contributors but not part of the supported contract
## Testing
Test fixtures are organized by diagram type:
- `tests/fixtures/flowchart/*.mmd` — flowchart fixtures
- `tests/fixtures/class/*.mmd` — class diagram fixtures
- `tests/fixtures/sequence/*.mmd` — sequence diagram fixtures
Snapshots follow the same structure: `tests/snapshots/flowchart/*.txt`, `tests/svg-snapshots/flowchart/*.svg`.
Key test files:
- `tests/integration_full.rs` — full-pipeline rendering tests
- `tests/compliance_class.rs` — class diagram compliance
- `tests/compliance_sequence.rs` — sequence diagram compliance
- `tests/mmds_json.rs` — MMDS JSON contract tests
- `tests/svg_render.rs` — SVG rendering tests
- `tests/cli.rs` — CLI integration tests
- `cargo xtask architecture` — repo-owned architecture policy enforcement
- `src/internal_tests/` — crate-local cross-pipeline tests (engine + routing + render)
The xtask architecture command enforces the semantic boundary rules in
`docs/architecture/dependency-rules.md`. `boundaries` owns semantic top-level
dependency policy across production and test code.
### Snapshot Regeneration
Text and SVG snapshots are checked into the repo. Each diagram type has its own env var and test target. Regenerate only the type you changed:
```bash
# Flowchart
GENERATE_TEXT_SNAPSHOTS=1 cargo nextest run -E 'test(generate_baseline_snapshots)'
GENERATE_SVG_SNAPSHOTS=1 cargo nextest run -E 'test(svg_snapshot_all_fixtures)'
# Class
GENERATE_CLASS_TEXT_SNAPSHOTS=1 cargo nextest run --test compliance_class -E 'test(class_text_snapshots)'
GENERATE_CLASS_SVG_SNAPSHOTS=1 cargo nextest run --test compliance_class -E 'test(class_svg_snapshots)'
# Sequence
GENERATE_SEQUENCE_TEXT_SNAPSHOTS=1 cargo nextest run --test compliance_sequence -E 'test(sequence_text_snapshots)'
```
## Debug Infrastructure
The project includes tooling to compare mmdflux layout against dagre.js v0.8.5.
### Setup
```bash
./scripts/setup-debug-deps.sh # Clone dagre and mermaid to deps/
```
### Parity Tests
```bash
cargo nextest run -E 'test(dagre_parity)' # Compare layout against dagre.js fixtures
```
### Refreshing Fixtures
```bash
./scripts/refresh-parity-fixtures.sh # Regenerate from dagre.js
```
### Debug Environment Variables
- `MMDFLUX_DEBUG_LAYOUT=<file>` - Write layout JSON
- `MMDFLUX_DEBUG_PIPELINE=<file>` - Write pipeline stages (JSONL)
- `MMDFLUX_DEBUG_BORDER_NODES=1` - Print border node trace
- `MMDFLUX_DEBUG_ORDER=1` - Order debug tracing
- `MMDFLUX_DEBUG_BK_TRACE=1` - Brandes-Köpf coordinate assignment trace
### Debug Scripts
- `scripts/dump-dagre-layout.js` - Run dagre.js layout
- `scripts/dump-dagre-pipeline.js` - Trace dagre pipeline stages
- `scripts/dump-dagre-borders.js` - Extract dagre border nodes
- `scripts/dump-dagre-order.js` - Dump node order per rank
See `docs/DEBUG.md` for comprehensive documentation.