- Use Scala 3.7; run
./mill __.reformatbefore committing. - All code must pass
./mill __.compile(includes WartRemover checks). - Run
./mill __.testto verify all tests pass. - Pre-commit hooks will automatically check formatting and compilation.
XL uses pre-commit hooks to automatically verify code quality before commits.
- Install pre-commit framework:
pip install pre-commit
# or: brew install pre-commit- Install the git hook scripts:
cd /path/to/xl
pre-commit install- (Optional) Run against all files to verify setup:
pre-commit run --all-filesThe hooks automatically run on git commit and verify:
- Scalafmt formatting (
./mill __.checkFormat) - Compilation (
./mill __.compile- includes WartRemover) - Trailing whitespace removal
- End-of-file newlines
- YAML validity (.yml/.yaml files)
- Merge conflicts detection
- Large files prevention (>1MB)
If any check fails, the commit is aborted with a clear error message.
Run hooks manually without committing:
# Run all hooks
pre-commit run --all-files
# Run specific hook
pre-commit run scala-compile --all-files
pre-commit run scalafmt-check --all-files"Command not found: pre-commit"
- Install via
pip install pre-commitorbrew install pre-commit
"Hook failed but I want to commit anyway"
- Not recommended, but use
git commit --no-verifyto skip hooks - Fix the issues first - hooks prevent broken code from entering the repository
"Compilation is slow in pre-commit"
- Hooks use Mill's incremental compilation (fast for small changes)
- Initial run may be slower (~10s), subsequent runs are <2s
XL uses WartRemover to enforce purity and totality. Your code must pass all Tier 1 warts (errors):
- No
null,.head,.tail,.geton Try/Either - See
docs/design/wartremover-policy.mdfor complete policy
Tier 2 warts (warnings) are monitored but don't fail builds:
.geton Option is acceptable in test codevar/while/returnare acceptable in performance-critical macros
- Add property tests for new laws; expand golden corpus.
- Test coverage goal: 90%+ with property-based tests for all algebras.
- Use MUnit + ScalaCheck for property tests.
XL follows strict coding conventions to maintain purity, totality, and law-governed semantics:
- Prefer opaque types for domain quantities (Column, Row, ARef, etc.)
- Use enums for closed sets;
derives CanEqualeverywhere - Use final case class for all data model types (prevents subclassing, enables JVM optimizations)
- Keep public functions total; return ADTs (Either/Option) for errors
- Prefer extension methods over implicit classes
- Macros must emit clear diagnostics; avoid surprises in desugaring
- Keep printers deterministic; update canonicalization when structures change
- Document every new public type in
/docswith examples
For detailed style rationale and examples, see docs/design/purity-charter.md and CLAUDE.md.