ADR-0002: Multi-Module Structure
Date: 2026-03-25 Status: Accepted
Context
The original jPipe compiler was a single Maven module. All concerns — grammar, domain model, operator logic, pipeline execution, and CLI — were mixed together, making it difficult to test components in isolation, extend the operator system, or reuse the compiler outside the CLI context.
Decision
Split the compiler into five Maven modules with a strict one-way dependency chain:
jpipe-cli → jpipe-compiler → jpipe-model
↘
jpipe-lang ──┘
jpipe-operators → jpipe-model
Module responsibilities
jpipe-lang
Contains the ANTLR4 grammar (JPipe.g4) and the generated lexer/parser. Nothing else. No domain knowledge, no interpretation logic. Consumers depend on this module to get a parse tree from source text.
jpipe-model
Contains the domain model: justification elements (Evidence, Strategy, Conclusion, SubConclusion, AbstractSupport), justification models (Justification, Template), and the symbol table. No parsing, no I/O, no operator logic.
jpipe-operators
Contains the CompositionOperator interface (the extension point for user-defined operators) and the built-in operators (assemble, merge, refine). Depends on jpipe-model to manipulate elements. External projects that define custom operators depend only on this module.
jpipe-compiler
Contains the compiler pipeline: reads a parse tree from jpipe-lang, builds a model using jpipe-model, validates it, applies operators from jpipe-operators, and produces exportable output. No CLI concerns.
jpipe-cli
Contains the command-line interface (Picocli), output rendering, and the fat JAR entry point. Depends on jpipe-compiler. This is the only module that pulls in runtime dependencies (Log4j2 core, org.json).
Consequences
- Custom operator authors depend only on
jpipe-operators— they are isolated from grammar and pipeline changes. - The compiler pipeline can be embedded in other tools (IDE plugins, CI integrations) by depending on
jpipe-compilerwithout the CLI. jpipe-langcan be regenerated at any time from the grammar without affecting the rest of the codebase.- Module boundaries must be respected: no upward dependencies (e.g.,
jpipe-modelmust never import fromjpipe-compiler).