# Technical Documentation: apache/incubator-kie-drools

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/apache/incubator-kie-drools)

### Overview (README.md)

# Apache KIE

<p align="left"><img src="./docsimg/kie-logo.svg" alt="Apache KIE logo" width="140"></p>

This is the main repository for [Apache KIE](https://kie.apache.org) (incubating). It contains the source code for:

- [**Drools**](https://kie.apache.org/components/drools/) — a rule engine, DMN engine, and complex event processing (CEP) engine for Java. 
- [**OptaPlanner**](https://kie.apache.org/components/optaplanner/) — a constraint solver for Java.
- [**jBPM**](https://kie.apache.org/components/jbpm/) — a workflow engine, and BPMN engine for Java.
- [**Kogito**](https://kie.apache.org/components/kogito/) — a cloud-native runtime for highly scalable business automation solutions based on Drools and jBPM. Available for [Quarkus](https://quarkus.io), and [Spring Boot](https://spring.io/projects/spring-boot).

---

## Drools

<p align="left"><img src="./docsimg/drools-logo.svg" alt="Drools logo" width="70"></p>

The rule engine in Drools is a business rule management system with a forward-chaining and backward-chaining inference, allowing fast and reliable evaluation of business rules and complex event processing. A rule engine is also a fundamental building block to create an expert system which, in artificial intelligence, is a computer system that emulates the decision-making ability of a human expert.

Rules are defined in the [DRL language](https://kie.apache.org/docs/10.2.x/drools/drools/language-reference/index.html), as source code or as Decision Table spreadsheets in Excel format.

The decision engine in Drools executes decision models. Decision models are a fundamental building block to separate decision logic from application code and put it in the hands of business experts.

Decisions models are defined in the [DMN notation](https://www.omg.org/spec/DMN/) with expressions written in the [FEEL language](https://kiegroup.github.io/dmn-feel-handbook/#dmn-feel-handbook).

The complex event processing (CEP) engine in Drools detects patterns in streams of events, correlating facts over time with temporal operators, sliding windows, and automatic event expiration. It is a fundamental building block to react to situations that emerge from the combination of many events over time — such as fraud detection, systems monitoring, and IoT applications — rather than from any single event alone.

Event processing rules are defined in the DRL language too, with facts declared as events and evaluated by the rule engine running in stream mode.

## OptaPlanner

<p align="left"><img src="./docsimg/optaplanner-logo.svg" alt="OptaPlanner logo" width="70"></p>

The constraint solver in OptaPlanner optimizes planning and scheduling problems, such as vehicle routing, employee rostering, task assignment, and school timetabling. It combines optimization heuristics and metaheuristics — such as tabu search, simulated annealing, and late acceptance — with very efficient incremental score calculation to find good solutions to NP-hard problems in reasonable time.

Planning problems and their constraints are defined in plain Java, with domain classes annotated as planning entities and score rules written with the Constraint Streams API or in the DRL language.

## jBPM

<p align="left"><img src="./docsimg/jbpm-logo.svg" alt="jBPM logo" width="70"></p>

The workflow engine in jBPM allows the definition and execution of business processes, bridging the gap between business analysts and developers by describing process logic in a notation both can understand. It supports long-running, stateful processes with human tasks, timers, events, and compensation, making it a fundamental building block to automate and monitor end-to-end business workflows.

Processes are defined in the [BPMN 2.0](https://www.omg.org/spec/BPMN/2.0/) notation.

## Kogito

<p align="left"><img src="./docsimg/kogito-logo.svg" alt="Kogito logo" width="70"></p>

The runtime in Kogito executes business automation solutions as cloud-native microservices, building on [Quarkus](https://quarkus.io) and [Spring Boot](https://spring.io/projects/spring-boot) to deliver fast startup, low footprint, and native compilation with GraalVM. It turns business assets into runnable microservices through build-time code generation, making it a fundamental building block to deploy rules, decisions, and processes as highly scalable microservices.

Kogito microservices are built using the same assets used by Drools and jBPM — DRL rules, DMN decisions, and BPMN 2.0 processes.

---

## Releases

Officially, Apache KIE releases are source code releases. They are available at the
[Apache KIE :: Downloads](https://kie.apache.org/downloads), or directly at
[downloads.apache.org/incubator/kie](https://downloads.apache.org/incubator/kie/), signed with the keys in
[KEYS](https://downloads.apache.org/incubator/kie/KEYS) — see the
[verification instructions](https://www.apache.org/info/verification.html).

For convenience, binary artifacts are published to [Maven Central](https://central.sonatype.com) under the following groupIds:

- `org.kie`
- `org.drools`
- `org.jbpm`
- `org.optaplanner`
- `org.kie.kogito`

To manage the versions of individual artifacts on your projects, import one of the BOMs:

- `org.drools:drools-bom`
- `org.optaplanner:optaplanner-bom`
- `org.kie.kogito:kogito-bom`

> There is no separate BOM for jBPM: its engine runs as part of Kogito, so the `org.jbpm` artifacts are managed by `org.kie.kogito:kogito-bom`.

All artifacts of a release share the same version, regardless of groupId.

## Documentation

For the documentation of Drools, OptaPlanner, jBPM, and Kogito, please see [Apache KIE :: Documentation](https://kie.apache.org/documentation)

Documentation about this repository itself — its structure, build, and conventions — lives in the [docs/](./docs/README.md) directory.

## Get involved

- Mailing lists:
  - [users@kie.apache.org](https://lists.apache.org/list.html?users@kie.apache.org) ([subscribe](mailto:users-subscribe@kie.apache.org)) — questions about using Apache KIE
  - [dev@kie.apache.org](https://lists.apache.org/list.html?dev@kie.apache.org) ([subscribe](mailto:dev-subscribe@kie.apache.org)) — development discussions
  - [commits@kie.apache.org](https://lists.apache.org/list.html?commits@kie.apache.org) ([subscribe](mailto:commits-subscribe@kie.apache.org)) — commit notifications
- Chat:
  - [Apache KIE @ Zulip](https://kie.zulipchat.com)
  - [Kogito @ Google Group](https://groups.google.com/g/kogito-development)
- Issues:
  - [apache/incubator-kie](https://github.com/apache/incubator-kie/issues) — this repository's issue tracker
  - [apache/incubator-kie-issues](https://github.com/apache/incubator-kie-issues/issues) — existing issues
- New to Apache? Check out:
  - [The Apache Way](https://www.apache.org/theapacheway/)
  - [Apache Newcomers guide](https://community.apache.org/newcomers/)
  - [Apache Incubator](https://incubator.apache.org)

## Building and contributing

```bash
git clone https://github.com/apache/incubator-kie.git
cd incubator-kie
mvn clean install -DskipTests
```

See [CONTRIBUTING.md](./CONTRIBUTING.md) for the contribution guide, and [docs/BUILDING.md](./docs/BUILDING.md) for build flags, test profiles, and troubleshooting.

## License

Licensed under the [Apache License, Version 2.0](./LICENSE).

---

Apache KIE (incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the name of Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.

Some of the incubating project’s releases may not be fully compliant with ASF policy. For example, releases may have incomplete or un-reviewed licensing conditions. What follows is a list of known issues the project is currently aware of (note that this list, by definition, is likely to be incomplete):

Some files, particularly test files, and those not supporting comments, may be missing the ASF Licensing Header
If you are planning to incorporate this work into your product/project, please be aware that you will need to conduct a thorough licensing review to determine the overall implications of including this work. For the current status of this project through the Apache Incubator visit: https://incubator.apache.org/projects/kie.html

---

### README (`docs/README.md`)

# Documentation

This directory centralizes documentation about how this repository works — its
structure, its build, and its conventions. User documentation for Drools, OptaPlanner, jBPM, and Kogito lives on
[Apache KIE :: Documentation](https://kie.apache.org/docs/documentation/).

## In this directory

| Document | What it covers |
| --- | --- |
| [STRUCTURE.md](./STRUCTURE.md) | The module prefix structure, the BOM/parent-pom hierarchies, and architectural notes |
| [BUILDING.md](./BUILDING.md) | How to build the repo, useful Maven flags and profiles, and troubleshooting |
| [DEV.md](./DEV.md) | Building only the modules your changes affect, with `make dev` |
| [CONVENTIONS.md](./CONVENTIONS.md) | Code style, licensing, dependency rules, testing and codegen conventions |
| [PR_CHECKS_AND_CI.md](./PR_CHECKS_AND_CI.md) | The checks that run on pull requests, and how CI builds the repo |
| [DEVELOP_ON_MACOS.md](./DEVELOP_ON_MACOS.md) | Setting up macOS for GraalVM native image builds |
| [OTHER_COMPONENTS.md](./OTHER_COMPONENTS.md) | Apache KIE components beyond the four main projects: the PMML engine and KIE Tools |
| [HISTORY.md](./HISTORY.md) | How KIE started, its initiatives over the years, and the move to Apache |

## At the repository root

- [README.md](../README.md) — project introduction
- [CONTRIBUTING.md](../CONTRIBUTING.md) — contribution guide (issues, PRs, dependency requirements)

---

### BUILDING (`docs/BUILDING.md`)

# Building

## Prerequisites

- Java SDK 17 or 21 (OpenJDK recommended) — CI builds with both — and Git
- Docker — not strictly required, but needed by some integration tests
  (Testcontainers-based); those tests can be skipped
- For GraalVM native image builds, follow the
  [Quarkus guide](https://quarkus.io/guides/building-native-image); on macOS,
  see [DEVELOP_ON_MACOS.md](./DEVELOP_ON_MACOS.md)

## Basic build

Build with Maven from the root:

```bash
mvn clean install
```

A full build with all tests takes a long time. Common ways to shorten the
cycle:

| Flag | Effect |
| --- | --- |
| `-DskipTests` | Skip unit and integration tests |
| `-DquickTests` | Formatting validation and unit tests only (skips invoker and archetype tests) |
| `-DskipITs` | Skip integration tests only (failsafe) |
| `-Dinvoker.skip=true` | Skip maven-invoker-based integration tests (e.g. in `kie-maven-plugin`) |
| `-Dquickly` | Skip most plugins and tests |
| `-Dfull` | Also build distribution modules (`fullProfile`) |

You can also build only the module you work on, plus what depends on it, with
standard Maven reactor flags (`-pl <module> -am` / `-amd`).

## Tests

- Unit tests run with surefire; integration tests run with failsafe and are
  named with a trailing `IT` (e.g. `SomethingIT.java`).
- Some tests assume an `en_US` locale. On machines with a different locale,
  activate the `test-en` profile: `-Ptest-en` or `-DTestEn`.
- Test coverage (Jacoco): `mvn clean verify -Ptest-coverage`, report under
  `target/site/jacoco/`.
- Quarkus modules: `@QuarkusTest` classes are unit tests (surefire),
  `@QuarkusIntegrationTest` classes are integration tests (failsafe,
  `*IT.java`). The two cannot be mixed in the same `integration-test` phase.
- Maven-invoker-based integration tests (which build real kjars with the KIE
  Maven plugin) support running a subset with `-Dinvoker.test=<pattern>`;
  their build logs land under `target/it/<module_name>/build.log`.

## Troubleshooting

- **`UnmappableCharacterException` during the build**: set
  `MAVEN_OPTS=-Dfile.encoding=UTF-8` (as an environment variable, not a `mvn`
  argument) and rebuild.
- **Testcontainers fails with "Can not connect to Ryuk at localhost"** (seen
  with some Docker for Mac versions, or when privileged containers are not
  allowed): try `export TESTCONTAINERS_RYUK_DISABLED=true`.
- **Locale-dependent test failures**: use the `test-en` profile described
  above.

---

### CONVENTIONS (`docs/CONVENTIONS.md`)

# Conventions

## Code style

- Configure your IDE with the shared formatter and import order files from
  [`kogito-build/kogito-ide-config/src/main/resources/`](../kogito-build/kogito-ide-config/src/main/resources/):
  - **Eclipse**: import `eclipse-format.xml` under *Preferences > Java > Code
    Style > Formatter*, and `eclipse.importorder` under *Organize Imports*.
  - **IntelliJ IDEA**: install the *Eclipse Code Formatter* plugin, point it at
    `eclipse-format.xml`, enable *Optimize Imports*, and use
    `eclipse.importorder`.
  - **VS Code**: install the *Checkstyle for Java* extension and set
    `eclipse-format.xml` as the Checkstyle configuration file.
- No `@author` tags in Javadoc — Git history tracks authorship.
- Prefer readability over conciseness: self-explanatory method names,
  meaningful variable names, small classes with a single clear responsibility,
  and methods that don't depend on hidden state established by their callers.

## Licensing

- Every source file carries the ASF license header. This is enforced in CI
  (`ci_check_license_headers` workflow). To format headers automatically:

  ```bash
  mvn com.mycila:license-maven-plugin:format
  ```

- Dependency licensing rules (Apache-2.0-compatible only, available on Maven
  Central, no fat/shaded jars, sources public, …) are spelled out in
  [CONTRIBUTING.md](../CONTRIBUTING.md#requirements-for-dependencies).

## Service discovery (SPI)

Two discovery mechanisms are used across the codebase:

- **Standard Java SPI** (`src/main/resources/META-INF/services/`) — used by
  Efesto plugins (`KieCompilerService`, `KieRuntimeService`) and the PMML
  engine.
- **KIE service discovery** (`META-INF/kie.conf`) — the traditional Drools
  mechanism; e.g. `drools-mvel` registers its implementations there, and
  missing implementations are reported centrally by
  `org.drools.core.base.CoreComponentsBuilder`.

## Code generation

Code generation is used by several engines (Drools executable model, Kogito
codegen, PMML). Shared principles:

- **Generate the code you would write by hand** if there were no codegen step —
  and before opening a PR, read the generated code and check that it does.
- Generation is JavaParser-based and template-driven; prefer manipulating the
  AST over plain string replacement. Template files use the `.tmpl` extension
  (PMML) or live under `src/main/resources/class-templates/` named
  `<Something><Runtime>Template.java` with `$…$` placeholders (Kogito).
- Prefer framework-specific templates plus shared plain classes over
  framework-agnostic templates patched by annotators. A template with no
  placeholders should be promoted to a plain shared class.
- In generated DI code, favor constructor injection; REST endpoints are the
  exception (field injection, no inheritance).

## Testing

- Integration test classes are named `*IT.java` (failsafe); everything else is
  a unit test (surefire). See [BUILDING.md](./BUILDING.md) for the flags and
  Quarkus-specific annotations.
- Include tests with every PR — existing unit tests are treated as the
  compatibility contract when refactoring.
- After significant refactoring of an engine, run the corresponding benchmarks
  in [incubator-kie-benchmarks](https://github.com/apache/incubator-kie-benchmarks)
  to catch performance regressions.

## Documentation

- Architecture and design diagrams are authored as PlantUML `.puml` files.
- Reference documentation for end users belongs to the
  [Apache KIE website](https://kie.apache.org/docs/documentation/), not this
  repository. Documentation about how *this repository* works belongs in
  [docs/](./README.md).

---

### DEV (`docs/DEV.md`)

# Building partially, with `make dev`

This repository has more than 850 Maven modules, so building all of them to
check a change in one is rarely what you want. CI already avoids that on pull
requests — it works out which modules a change can possibly affect and builds
only those (see [PR_CHECKS_AND_CI.md](./PR_CHECKS_AND_CI.md)). `make dev` gives
you the same thing locally, driven by your working copy instead of a pull
request.

It uses the very same scope computation CI runs, so the modules it builds are
the modules CI will build. By default it looks at what you have edited but not
committed, and skips tests — that is the inner loop, and CI is the safety net;
`make dev mvn -- install` runs the tests when you want them.

## What it does

- **Builds only what your change affects.** The same computation CI runs on pull
  requests, applied to your working copy.
- **Optimises for the inner loop.** By default it looks at uncommitted work only,
  skips tests and the reporting plugins, and builds in parallel.
  `make dev mvn -- install` runs the tests when you want them.
- **Rebuilds stale dependencies for you.** Anything missing from `~/.m2`, or
  older than the sources it was built from, is rebuilt first — so switching
  branches or a fresh clone does not silently build against the wrong artifacts.
- **Remembers its settings.** Four lines in `.kie-dev/config.properties`, written on the
  first run and editable by hand.
- **Lets you say what "your changes" means.** Since this branch started, or since
  your last commit — with or without uncommitted work.
- **Shows you before it builds.** `make dev scope` prints the module list and
  builds nothing.
- **Stays out of the way of Maven.** `make dev mvn -- …` passes your command
  straight through, so any goal, profile or flag still works.
- **Caches the expensive part.** The reactor dependency graph is read once and
  reused until a `pom.xml` changes, which is the difference between a two-second
  and a forty-second start.
- **Works from a plain shell.** Your Maven if you have one, the devbox copy if
  you do not.

## Getting started

```bash
make dev
```

That is the whole thing. The first run writes `.kie-dev/config.properties` with sensible
defaults and tells you so; edit that file, or override any setting for a single
run.

The only prerequisites are [JBang](https://www.jbang.dev), Maven and git on your
`PATH` — this repository provides the first two through
[devbox](https://www.jetify.com/devbox), so `devbox shell` gets you all of them.
If one is missing you are told which, rather than left with a stack trace. You do not need to have built the repository first — dependencies that
are missing from `~/.m2`, or that are older than their sources, are rebuilt
automatically. See [Upstream modules](#upstream-modules) below.

The Makefile is dedicated to these partial builds. Full builds are plain
Maven — see [BUILDING.md](./BUILDING.md).

## Cheatsheet

Every knob, in one place.

### Commands

| Command | Does |
| --- | --- |
| `make dev` | Build what your changes affect, using the saved settings |
| `make dev scope` | Print what would be built; build nothing |
| `make dev config` | Show the current settings |
| `make dev mvn -- <mvn args>` | Build them with your own Maven command |
| `make help` | List the targets and summarise the above |

### Settings

Four settings, in precedence order: **command line** → **`.kie-dev/config.properties`** → **default**.

| Setting | Values | Default |
| --- | --- | --- |
| `since` | any git ref | `HEAD` |
| `uncommitted` | `true`, `false` | `true` |
| `breadth` | `changed`, `affected` | `affected` |
| `upstream` | `auto`, `always`, `never` | `auto` |

```bash
make dev since=origin/main   # this run only, not saved
make dev config              # show what is saved
```

<details>
<summary>What each value means</summary>

| `since` | Committed changes are measured from |
| --- | --- |
| `HEAD` | nothing committed — your working tree alone. The default |
| `origin/main` | where this branch was branched from main |
| `HEAD~1` | your last commit |
| any ref | `git merge-base <ref> HEAD` |


| `uncommitted` | The working tree                                |
| ------------- | ----------------------------------------------- |
| `true`        | added on top: `git diff HEAD` + untracked files |
| `false`       | ignored; only committed work counts             |

| `breadth`  | Modules built                                 |
| ---------- | --------------------------------------------- |
| `changed` | the modules whose files changed |
| `affected` | those plus everything transitively downstream — the default, as CI builds |

| `upstream` | Dependencies rebuilt first, with tests skipped                                                        |
| ---------- | ----------------------------------------------------------------------------------------------------- |
| `auto`     | those missing from the local repository or older than their sources, plus anything downstream of them |
| `always`   | all of them                                                                                           |
| `never`    | none; no check is run                                                                                 |

</details>

### Maven arguments

`make dev` builds fast: parallel, fail-at-end, and skipping tests, enforcer,
checkstyle, formatter and ArchUnit. That is the inner loop — CI is what runs the
tests.

When you want something else, `make dev mvn -- <mvn args>` takes the Maven command itself.
Everything after `--` replaces the default entirely:

```bash
make dev mvn -- install                    # the same modules, with tests
make dev mvn -- clean install -Pfull
make dev mvn -- test -Dtest=MyTest
```

`--` is required — without it Make treats `-DskipTests` as one of its own
options. `make dev mvn` with nothing after the `--` is an error rather than a silent
second spelling of `make dev`.

### Config file

`.kie-dev/config.properties`, an ordinary Java properties file, safe to edit by hand:

| Key             | Value                                                          |
| --------------- | -------------------------------------------------------------- |
| `since` | as above |
| `uncommitted` | as above |
| `breadth` | as above |
| `upstream` | as above |

### Environment variables

| Variable                                                                      | Effect                                                                                                         |
| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `KIE_DEV_SINCE`, `KIE_DEV_UNCOMMITTED`, `KIE_DEV_BREADTH`, `KIE_DEV_UPSTREAM` | What the `since=`/`breadth=`/`uncommitted=`/`upstream=` overrides set |
| `MVN`                                                                         | Maven binary to run. Otherwise `mvn` from `PATH`, then the devbox copy under `.devbox/`                        |
| `MAVEN_OPTS`                                                                  | Passed through to Maven as usual                                                                               |
| `NO_COLOR`                                                                    | Disables coloured output                                                                                       |
| `DEP_GRAPH_EXTRACTOR__JAR`                                                    | Use a prebuilt extractor jar instead of building one                                                           |
| `DEP_GRAPH_EXTRACTOR__EXTRA_MAVEN_ARGS`                                       | Extra args for the graph extraction run, e.g. `-Psome-profile`                                                 |

`DEP_GRAPH_EXTRACTOR__OUTPUT_FILE` and `DEP_GRAPH_EXTRACTOR__REUSE_IF_FRESH`
also exist, but `make dev` sets both itself, so setting them in the
environment has no effect here. They are how CI runs the same script without the
cache — see [PR_CHECKS_AND_CI.md](./PR_CHECKS_AND_CI.md).

### State files

All under `.kie-dev/`, all disposable — delete the directory to reset.

| File                                                   | Contents                                      |
| ------------------------------------------------------ | --------------------------------------------- |
| `config.properties` | your saved settings |
| `dep-graph.tsv` | the reactor dependency graph, cached between runs |
| `dep-graph.tsv.stamp` | fingerprint of every `pom.xml`, which invalidates that graph |
| `changed-files.txt`                                    | changed files from the last run               |
| `modules-to-build.txt`                                 | the modules the last run built                |
| `upstream-modules.txt`                                 | the upstream modules it rebuilt first, if any |
| `last-maven-command.txt`                               | the Maven commands it issued, in full         |
| `pl-changed.txt`, `pl-affected.txt`, `pl-upstream.txt` | the computed scopes from the last run         |

Module lists and Maven commands are printed as a count rather than in full — a
`-pl` argument with several hundred coordinates in it is not something anyone
reads. The files above are where the real thing lives, for when you need to
copy, paste or debug it.

### Tests

```bash
jbang script/dev/tests/DevTest.java
jbang script/dev/tests/MakefileTest.java
```

## Upstream modules

A partial build can only resolve dependencies that are already installed in
`~/.m2`, and it only gives correct results if what is installed was built from
the sources you have now. Both go wrong routinely: the first time you use the
repository nothing is installed at all, and after switching branches or pulling,
what is installed no longer matches your working copy.

So before the main build, the tool works out which of its dependencies cannot be
trusted, and rebuilds exactly those with tests skipped:

- **not installed** — no artifact in the local Maven repository;
- **older than its sources** — the installed artifact predates a file in the
  module it was built from;
- **downstream of either** — a module whose own dependency is being rebuilt.

Typically nothing needs rebuilding and the check costs a second or so:

```
all 10 upstream modules are installed and up to date — nothing to rebuild
```

Otherwise it says what it is about to do, and why:

```
Upstream modules to rebuild first: 82  (.kie-dev/upstream-modules.txt)
    5 older than their sources, 77 downstream of those
```

This is controlled by `upstream`, which defaults to `auto` because `auto` is
almost always what you want:

| `upstream` | Behaviour                                                              |
| ---------- | ---------------------------------------------------------------------- |
| `auto`     | Rebuild only dependencies that are missing or out of date. The default |
| `always`   | Rebuild every dependency, like CI does                                 |
| `never`    | Trust `~/.m2` as it is, and skip the check                             |

```bash
make dev upstream=always   # when in doubt
make dev upstream=never    # when you know ~/.m2 is good and want the seconds back
```

Staleness is judged by file modification times, which is why `never` exists: if
something touches files without changing them, everything downstream will look
stale. Note also that this only reasons about modules *in this repository* —
dependencies from other repositories are ordinary Maven artifacts, and it is up
to you to have the right versions installed.

## How it works

1. `make dev` runs [`script/dev/Dev.java`](../script/dev/Dev.java), a single
   JBang script.
2. It turns `since` and `uncommitted` into a list of changed files, using
   `git diff` and `git ls-files`.
3. It hands that list to
   [`script/ci/CiComputeBuildScopes.java`](../script/ci/CiComputeBuildScopes.java) —
   the same script CI uses, pulled in directly as a JBang `//SOURCES`
   dependency rather than copied. It maps each changed file to its nearest
   reactor module and walks the dependency graph
   ([`DepGraph`](../script/ci/DepGraph.java), also shared) to produce three
   disjoint sets: `changed`, `affected` and `upstream`.
4. Your chosen breadth selects from those sets, and the result becomes a Maven
   `-pl` argument.
5. Separately, it walks the dependency graph *upwards* from what it is about to
   build, checks each of those modules against the local Maven repository, and
   rebuilds the ones that are missing or out of date in a first pass.

Step 5 does not reuse the `upstream` set from step 3. That set is relative to
the affected modules, whereas a `changed` build can need modules that sit inside
`affected` — everything is downstream of the root pom, including modules that
the root pom's own children depend on.

Reading the dependency graph means reading every `pom.xml` in the reactor, which
is too slow to repeat on every build. Locally the graph is therefore kept in
`.kie-dev/dep-graph.tsv` and reused until any `pom.xml` is added, removed or
edited — which takes a typical run from tens of seconds down to about two. CI
always computes the graph from scratch instead.

This is only about the dependency graph. It is unrelated to your local Maven
repository (`~/.m2`), which is what the [upstream modules](#upstream-modules)
check looks at.

## Troubleshooting

**"Nothing has changed since that point"** — nothing to build. If you have
committed your work and `since=HEAD`, switch to `since=origin/main`.

**"No reactor module matched the changed files"** — you only changed files that
live outside any Maven module, such as documentation or workflow files.

**"Cannot find a merge base"** — the recorded base is not present locally. Fetch
it (`git fetch origin main`), or point `since` at a ref you have.

**The build is far bigger than expected, and the base is a local branch** — it
has probably gone stale. `git fetch`, then either pull it or set
`since=origin/<branch>`.

**Maven cannot resolve a module of this repository** — the dependency check
believed it was installed and current. Force the issue with
`make dev upstream=always`, and please report it.

**It keeps rebuilding dependencies that look fine** — staleness is judged by
file modification times, so anything that rewrites files without changing their
contents will trigger it. Use `upstream=never` to skip the check.

**The build is far bigger than expected** — you have probably touched a parent
pom or a hub module, so almost everything is downstream of it. Confirm with
`make dev scope`, and use `breadth=changed` for a tighter loop.

## Tests

The script and the Makefile are covered by two suites. Run them if you change
[`script/dev/`](../script/dev/) or the [Makefile](../Makefile):

```bash
jbang script/dev/tests/DevTest.java
jbang script/dev/tests/MakefileTest.java
```

Both are hermetic and take a few seconds — they build throwaway git repositories
and dependency graphs in temp directories, and never build the reactor.

CI runs those in [dev-tests.yaml](../.github/workflows/dev-tests.yaml), along
with a job that runs `make dev` for real in a fresh clone.

## Related

- [BUILDING.md](./BUILDING.md) — building the whole repository, Maven flags and profiles
- [PR_CHECKS_AND_CI.md](./PR_CHECKS_AND_CI.md) — how CI uses the same scope computation
- [`script/dev/`](../script/dev/) and [`script/ci/`](../script/ci/) — the scripts themselves

---

### DEVELOP ON MACOS (`docs/DEVELOP_ON_MACOS.md`)

# Developing on macOS

## Setting up GraalVM for native image builds

Building native images requires GraalVM. The instructions below use
[SDKMAN!](https://sdkman.io) to manage JDK installations — not mandatory, but
recommended, as it makes switching JDKs during development easy.

Check the [Quarkus documentation](https://quarkus.io/guides/building-native-image#configuring-graalvm)
for the currently supported GraalVM version, and use it in place of
`<graalvm-version>` below.

1. Install SDKMAN!:

   ```bash
   curl -s "https://get.sdkman.io" | bash
   ```

2. Install [Homebrew](https://brew.sh):

   ```bash
   /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
   ```

3. Install GraalVM with Homebrew:

   ```bash
   brew install --cask graalvm/tap/<graalvm-version>
   ```

4. Register the GraalVM installation with SDKMAN!:

   ```bash
   sdk install java <graalvm-version>-grl /Library/Java/JavaVirtualMachines/<graalvm-version>/Contents/Home
   ```

5. In the module you want to build, switch to GraalVM and run the native
   build:

   ```bash
   sdk use java <graalvm-version>-grl
   mvn clean package -Pnative
   ```

---

### HISTORY (`docs/HISTORY.md`)

# History

KIE — short for *Knowledge Is Everything* — is a community of solutions and
supporting tooling for knowledge engineering and process automation, focusing
on events, rules, and workflows. The name has a history going back more than
two decades.

## Origins

The projects that make up Apache KIE predate the umbrella by many years.
Drools began in 2001 as an open source rule engine and grew into a full
business rule management system at JBoss, later Red Hat. OptaPlanner started
in 2006 as *Drools Planner* before becoming a project in its own right. jBPM
emerged at JBoss as a workflow engine for long-running business processes,
and from jBPM 5 (2010) onwards it was rebuilt around the same knowledge core
as Drools. The *KIE* umbrella name was introduced alongside Drools and jBPM 6
to bring the projects — engines, tooling, and shared infrastructure — under
one roof.

The community projects also served as the upstream for a line of commercial
offerings by Red Hat: JBoss Enterprise BRMS 5, Red Hat JBoss BPM Suite 6, and
Red Hat Process Automation Manager and Red Hat Decision Manager 7.

The Drools and jBPM 6 and 7 generations came with distinct components of
their own. **Guvnor** provided the web-based repository and authoring
environment for business rules and knowledge assets. It evolved into the KIE
Workbench, later rebranded as **Business Central** — a full web environment
for authoring, building, and managing rules, processes, forms, and dashboards.
**KIE Server** was the standalone execution server of that generation,
exposing REST APIs to run rules, processes, and plannings deployed as kjars.
These components were superseded by the cloud-native generation, with
authoring moving to KIE Tools and execution to Kogito.

For most of their history the projects were developed in the open on GitHub
under the [kiegroup](https://github.com/kiegroup) organization, sponsored by
Red Hat. In 2019, Kogito was announced — a continuation of Drools, jBPM, and
OptaPlanner, completely redesigned to be cloud-native — building on Quarkus
and code generation to run rules, decisions, and processes as microservices.

## Initiatives along the way

Beyond the engines, the KIE community incubated a number of initiatives over
the years, some of which grew into projects of their own:

- **[Dashbuilder](https://www.dashbuilder.org)** — a tool for authoring
  dashboards and visualizing business data, today part of KIE Tools.
- **[TrustyAI](https://github.com/trustyai-explainability)** — explainability
  and auditing for AI-augmented decision services; it continues today as an
  independent open source project. Traces of it remain in this repository
  (e.g. the `kogito-trusty` and `kogito-explainability` modules).
- **[SonataFlow](https://sonataflow.org)** — a workflow engine for building
  serverless applications, implementing the CNCF Serverless Workflow
  specification, grown out of Kogito.

## The move to Apache

In July 2022, Red Hat and IBM announced that IBM was joining the KIE
community, combining IBM's leadership in business automation with Red Hat's
leadership in open source, and shared their intent to move the technologies
to a foundation to widen the network of collaborators (see the
[announcement](https://web.archive.org/web/20240719040925/https://blog.kie.org/2022/07/ibm-rht.html)).

On January 13th, 2023, KIE entered the
[Apache Incubator](https://incubator.apache.org/projects/kie.html). The
repositories moved from `github.com/kiegroup` to `github.com/apache` under
the `incubator-kie-*` prefix, the community adopted the Apache Way, and the
project's home became [kie.apache.org](https://kie.apache.org).

The [kiegroup](https://github.com/kiegroup) organization forked back some repositories from Apache KIE as midstreams in order for Red Hat to keep maintaining its commercial offerings based on KIE.

---

### OTHER COMPONENTS (`docs/OTHER_COMPONENTS.md`)

# Other components

Besides Drools, OptaPlanner, jBPM, and Kogito, Apache KIE includes other
components worth knowing about.

## PMML engine

The PMML engine executes predictive models conforming to the
[PMML standard](https://dmg.org/pmml/pmml-v4-4-1.html) (Predictive Model
Markup Language, maintained by the Data Mining Group). It allows machine
learning models exported from data science tools to run alongside rules,
decisions, and processes — for example, a DMN decision invoking a predictive
model as part of its logic.

The engine lives in this repository, under the `kie-pmml-trusty` module.

## KIE Tools

[KIE Tools](https://github.com/apache/incubator-kie-tools) is a separate
repository hosting the tooling for authoring the business assets executed by
the engines: editors for BPMN, DMN, and DRL extensions for VS Code and Chrome, the online KIE Sandbox for authoring and sharing assets without any local setup.

---

### PR CHECKS AND CI (`docs/PR_CHECKS_AND_CI.md`)

# PR checks and CI

CI runs on GitHub Actions. Workflows live in
[`.github/workflows/`](../.github/workflows/); the logic they rely on lives in
[`script/ci/`](../script/ci/) as [JBang](https://www.jbang.dev) scripts, plus
local composite actions in [`.github/actions/`](../.github/actions/).

## `CI :: Build` — the main PR check

Defined in [ci.yaml](../.github/workflows/ci.yaml). Runs on every pull request
against `main`, and on every push to `main`. Documentation-only changes
(Markdown/AsciiDoc files, `LICENSE`, text files, images under `docsimg/`) do
not trigger it.

On a pull request it builds **only what the PR can affect**, instead of the
whole reactor:

1. The PR is checked out as a **simulated squashed merge** onto the base
   branch (via the local [`checkout-pr`](../.github/actions/checkout-pr)
   action), so the build sees exactly what `main` would look like after the
   merge.
2. The changed files are collected with a three-dot diff against the base
   branch.
3. [`CiComputeBuildScopes.java`](../script/ci/CiComputeBuildScopes.java) maps
   the changed files to two disjoint sets of Maven modules, using the
   dependency graph produced by
   [`dep-graph-extractor`](../script/ci/dep-graph-extractor/):
   - **upstream** — intra-reactor dependencies of the affected modules; built
     with tests skipped, just to populate the local repository;
   - **affected** — the changed modules plus everything transitively
     downstream of them; built with tests.
4. Both passes run with `-fae` (fail at end) so every broken module is
   reported, not just the first one, and the affected pass builds with
   `-Dreproducible`. Enforcer, Checkstyle, formatter and ArchUnit plugins are
   skipped in PR builds — they are validated elsewhere.
5. [`CiSummary.java`](../script/ci/CiSummary.java) publishes a build summary
   (including the computed scopes and test results) to the workflow run.

On a push to `main` it instead runs a full `mvn install` of the whole reactor,
with `-Dfull` (which additionally builds the distribution modules and Javadoc
JARs) and `-Dreproducible`.

Notes:

- The build matrix currently runs on Linux with Java 17 and 21; macOS and
  Windows are temporarily excluded because of Docker-dependent tests failing
  on non-Linux runners.
- The `apache.snapshots` Maven repository is blocked via a mirror in
  `settings.xml`, so builds cannot silently depend on snapshot artifacts.
- A new push to a PR cancels that PR's in-progress run, and so does closing
  or merging the PR. Runs for pushes to `main` are never canceled.
  `CI :: CI Tests` and `Dev :: Tests` follow the same rules.
- After the build, a Surefire report step fails the job on test failures, and
  the build logs (`build.log`) plus the reproducibility outputs
  (`*.buildcompare`, `*.buildinfo`) are uploaded as workflow artifacts.

To re-run the checks, push a new commit to the PR — an empty commit is enough:
`git commit --allow-empty -m "re-trigger CI"`.

## `CI :: Examples` — downstream check

Defined in [pr-downstream.yml](../.github/workflows/pr-downstream.yml). Runs
on every pull request against `main` (same documentation-only exclusions as
`CI :: Build`). It verifies that the PR does not break the
[apache/incubator-kie-kogito-examples](https://github.com/apache/incubator-kie-kogito-examples)
repository:

1. This repository is built and installed into the local Maven repository with
   tests skipped, so the examples resolve the PR's snapshot artifacts.
2. The examples repository is checked out and built — one matrix job per
   subfolder: `kogito-quarkus-examples`, `kogito-springboot-examples`, and
   `gradle-examples`.
3. A Surefire report step fails the job on test failures, and the Maven
   dependency trees are uploaded as workflow artifacts.

## `CI :: CI Tests`

Defined in [ci-tests.yaml](../.github/workflows/ci-tests.yaml). Snapshot tests
for the CI scripts themselves: the scenarios under
[`script/ci/tests/`](../script/ci/tests/) verify that build-scope computation
and summary generation behave as expected. If you change anything in
`script/ci/`, this is the check that guards it.

## `Dev :: Tests`

Defined in [dev-tests.yaml](../.github/workflows/dev-tests.yaml). Tests for the
local partial build — [`script/dev/`](../script/dev/) and the `dev` target
in the [Makefile](../Makefile). See [DEV.md](./DEV.md).

Two jobs. `Dev scripts` runs the two unit suites, which build throwaway git
repositories and dependency graphs in temp directories and never invoke Maven,
so it takes seconds. `make dev in a fresh clone` then runs `make dev` for real
on a checkout that has never been built, with the Maven cache deliberately
disabled — that is the case where the upstream pass has to notice nothing is
installed, so it does build, and takes minutes.

If you change anything under `script/dev/` or the Makefile, this is the check
that guards it.

## License header check

Defined in
[ci_check_license_headers.yaml](../.github/workflows/ci_check_license_headers.yaml).
Runs [Apache RAT](https://creadur.apache.org/rat/) on every PR and fails if
any file is missing the ASF license header. See
[CONVENTIONS.md](./CONVENTIONS.md#licensing) for how to format headers
automatically.

## Split package detection

Defined in
[split-package-detection.yml](../.github/workflows/split-package-detection.yml).
Detects Java packages split across multiple modules. The explicitly allowed
exceptions live in
[check-split-packages-allowed.txt](../script/split-packages/check-split-packages-allowed.txt);
introducing a new split package fails the check.

---

### STRUCTURE (`docs/STRUCTURE.md`)

# Repository structure

This repository hosts several Apache KIE projects, built together as a single
Maven reactor. All top-level modules are declared in the root
[pom.xml](../pom.xml).

## Module prefixes

Top-level modules are grouped by prefix:

| Prefix | What it is |
| --- | --- |
| `drools-` | The Drools rule engine: runtime, compiler, DRL language, executable model, and related tooling |
| `optaplanner-` | The OptaPlanner constraint solver |
| `kogito-` | The Kogito cloud-native runtimes: code generation, Quarkus/Spring Boot integrations, add-ons |
| `kogito-apps-` | The Kogito supporting services and their build infrastructure |

A `fullProfile` profile (activated with `-Dfull`) adds distribution modules
such as `drools-distribution` to the build.

## Parent poms and BOMs

Two parallel hierarchies exist:

**KIE/Drools side:**
- [`kie-parent`](../kie-parent) — main build configuration (plugins, profiles) for the Drools/KIE modules
- [`bom`](../bom) (`drools-bom`) — the artifacts distributed by the Drools side
- [`build-parent`](../build-parent), [`kie-quarkus-build-parent`](../kie-quarkus-build-parent) — build configuration layers

**Kogito side:**
- `kogito-bom` — every library distributed by Kogito; **any new Kogito module must be added there**
- `kogito-dependencies-bom` — all third-party dependencies, runtime-agnostic
- `kogito-build-no-bom-parent` — main entry point for build configuration (plugins, profiles); deliberately imports no Kogito BOM so the Quarkus Platform can control dependency management
- `kogito-build-parent` — inherits the above and imports `kogito-bom`; every internal Kogito module inherits from it
- `kogito-quarkus/bom` and `kogito-springboot/bom` — add the Quarkus / Spring Boot BOMs respectively

Rule of thumb when adding a dependency: runtime-specific dependencies go to the
respective runtime BOM; everything else goes to the dependencies BOM. See the
dependency requirements in [CONTRIBUTING.md](../CONTRIBUTING.md).


---

*Historical footnote: the `optaplanner-`, `kogito-` and `kogito-apps-` module
groups originate from formerly separate repositories that were folded into
this one; the root [pom.xml](../pom.xml) still marks those sections with
`BEGIN/END … modules (auto)` comments.*

---

--- METRICS ---
- Files Extracted: 10
- Estimated Token Budget: ~11496 tokens
- Canonical Reference: https://codewiki.google/github.com/apache/incubator-kie-drools
