01 · Workflow
Pin, change, compare
enola baseline pin
# make the change
enola checkbaseline pin creates the “before” snapshot. check builds the current snapshot, verifies that the two snapshots are comparable, and reports findings introduced by the change.
A changed Enola version, repository, or ignore configuration makes two snapshots non-comparable. Enola stops instead of reporting extraction noise as a code change.
If only the producer set differs, Enola grades facts from extractors and providers present in both snapshots. The result is marked PASS (partial verdict) or FAIL (partial verdict) and names every excluded producer and ungraded fact.
02 · Policy
Exit codes
| Code | Meaning | Action |
|---|---|---|
| 0 | No configured regression was introduced. | Continue. |
| 1 | The change introduced a finding covered by --fail-on. | Block the commit or job. |
| 2 | The check could not run, for example because no baseline exists. | Fix the invocation or repository state. |
| 3 | The snapshots are not comparable — for example, the Enola version, repository identity, or ignore configuration differs. | Review the receipts, then re-pin with the intended configuration. |
enola check --fail-on=layers enola check --fail-on=layers,cycles,intent enola check --fail-on=god-class --min-confidence=0.8 enola check --fail-on=layers --warn-only enola check --json enola check --detail enola check --focus=internal/auth enola check --target=internal/auth --max-spillover=0
--fail-on takes a comma-separated list of finding categories — layers, cycles, intent, god-class, hotspots, and the other categories defined in EXPLAINERS.md. There is no default: unset means nothing can fail. Only categories in the active list can produce exit code 1, and a name that matches no explainer matches nothing at all — enola check --json prints the policy that actually ran.
Two categories describe rather than complain: the finding that names which architecture pattern was matched, and the notice that a cluster config overrode a repo's own declaration. Both are exact, both are reported under Descriptive (never graded), and neither can fail a build — otherwise declaring a layer order would fail the very change that declared it.
--min-confidence filters findings by confidence before --fail-on is evaluated. Raise it to exclude lower-certainty estimates; proven load-order cycles carry confidence 1.0.
--warn-only downgrades a policy you set, so findings and spillover breaches report without producing exit code 1. Invocation errors and incomparable snapshots still return codes 2 and 3.
--focus narrows the reported delta. --target is different: it declares the area the change was meant to affect, computes the predicted reverse-dependency radius from the baseline, and reports touched packages outside it as spillover. Spillover remains advisory unless --max-spillover is set; 0 fails on any spillover.
03 · Automation
Automate the loop
enola baseline pin and enola check work independently of an agent. Run them from any client workflow, a pre-commit hook, or CI.
GitHub Actions
Add the Enola Architecture Check to .github/workflows/architecture.yml. It installs Enola, compares each pull request with its base commit, shows findings on affected lines, and summarizes the architectural change.
name: Architecture
on:
pull_request:
permissions:
contents: read
jobs:
enola:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: enola-labs/enola-action@v2
with:
fail-on: layersUsing another CI system? Run enola check --fail-on=… directly and use its exit code to pass or fail the job.
04 · Findings
Deterministic and heuristic checks
Cycle detection runs over the extracted import graph with Tarjan’s strongly connected components algorithm. Other findings—such as god classes, hotspots, dependency depth, and complexity outliers—depend on documented thresholds.
The result is bounded by extractor coverage. Dynamic imports, generated code, runtime registration, and unsupported framework behavior can leave edges unresolved. Treat the receipt and coverage report as part of the result.