Skip to content
@enola-labs

Enola

Building developer infrastructure for agentic era.

Enola Labs

Architectural regression testing for AI-assisted development.

GitHub Stars License MCP Protocol

WebsiteenolaGitHub ActionQuickstartDocsCLIBenchmarksArchitecture


Catch architecture regressions before they merge

Builds and tests verify that the code still works. Enola measures what the change did to the structure of the system: new dependencies, cycles, crossed boundaries and unintended spread.

It gives coding agents an exact architectural map before they edit, compares the graph afterward, and fails only the rules your team chose to enforce. The same verdict runs in the agent loop, a local shell and pull-request CI. Local, deterministic parsers extract the graph directly from multi-language source; no model or embeddings are involved.

go build and go vet both pass on a change that crosses a declared layer; enola check --fail-on=layers fails the same change, names the crossing, and after the fix the identical command goes green

The compiler was happy. storage now emails the buyer a receipt. go build and go vet both pass — nothing in the toolchain has an opinion about the innermost layer reaching the outermost one. The next command enforces the layer order this repository declared, the same change fails, and the fix makes the identical command go green.
A real run against examples/layers-gate — no editing, no compositing. No hosted service, API key or account. The four-line layer declaration lives beside the code. Nothing leaves the machine.


The loop

Before a change, your agent gets the real structure — modules, symbols, routes, storage and how they depend on each other, extracted from source rather than inferred. It can ask what actually depends on the thing it's about to touch, instead of guessing from a grep.

After a change, enola grades what the change did. It pins the architecture beforehand, compares afterwards, and reports the delta. It's a delta, not a linter — completely silent about everything that was already there, so when it does speak, something moved:

FAIL — 1 structural regression introduced.

Regressions (fail):
  - [layers] 1.00 — Layer violation: storage -> delivery
      import of notify

Policy: fail on new findings from [layers] at confidence >= 1.00.

Runs in your agent as a hook, in your shell (enola check to report; enola check --fail-on=layers to enforce), and in CI via the GitHub Action — the same verdict and policy in all three.

Nothing fails out of the box. All eighteen explainers run, every finding is reported, and the default run exits 0 while stating that nothing was enforced. You choose what breaks: --fail-on=layers,cycles,intent,constraints, or a change that spread beyond the scope you declared. What counts as an architectural regression is a decision about your codebase; Enola measures the change and makes the active policy explicit. See exactly what can fail and how confidence affects it.

Not a language model, and not embeddings: tree-sitter plus language-specific extractors, a typed fact model, and real graph algorithms. The same commit yields the same answer — across 91 open-source repositories indexed three times each, once cold and twice warm, all 91 produced a byte-identical snapshot ID and a byte-identical fact file: 273 runs, 8.0 million facts, zero parse errors, zero drift. Nothing leaves your machine.


Beyond the gate

The graph is the substrate; the check is one thing built on it.

  • Declared intent — layer order, cross-repo seams and knowledge pages compile into the graph, so what you meant is a fact your agent can query, not a comment.
  • A repository's law — what this codebase is not allowed to do, in 21 rule forms, bound from shipped recipes in one command or written as sentences in Ruby.
  • The provider seam — facts enola did not extract, admitted fail-closed: Rubydex, Prism, runtime capture, RBS/Sorbet.
  • Historyblame and diff over a shareable store, for the question a single snapshot structurally cannot answer: when did this happen?
  • 19 MCP tools and eighteen explainers, all of it in the open-source engine — nothing gated, metered or degraded behind a key.

docs/ is the map: every page and the question it answers.


Ecosystem

  • enola-labs/enola — the engine: extractors, cross-repo linker, MCP server, CLI and the check gate. Written in Go, Apache 2.0, and it is the whole engine.
  • enola-labs/enola-action — the GitHub Action. Two lines in a workflow file and every pull request is graded against its own base: new findings as source annotations, the structural delta in the job summary, and the same exit code as enola check. No baseline artifact to publish or restore, and the source never leaves the runner.
  • enola-labs/enola-rb — four pure-Ruby gems. enola wraps the released binary, fetches it on first use and forwards every command and exit code unchanged; enola-rb adds the Rails layer — a generator plus enola:snapshot and enola:check rake tasks. munola and munola-rb are the same pair over a second channel.
  • enola-labs/enola-guides — the content layer: guides, worked examples, recipes, twenty-six complete laws, skills and templates, packaged as a gem so a team can pin the guidance it adopted.

The last two are forks. Both were created and are maintained by Muhamed Isabegović, at misabegovic/enola-rb and misabegovic/enola-guides. enola-labs keeps them in step to carry the attribution and to endorse them as the Ruby and Rails integration for enola; the published gems come from upstream, and issues and pull requests belong there.

Rails, end to end

bundle add enola-rb
bin/rails generate enola:install
bin/rake enola:check

The generator writes the starter laws, binds the shipped recipes whose roles resolve in your app, and turns both Ruby fact providers on. Rails routes across every engine and plugin route file, mount composed into the mounted engine's own routes, Grape APIs found by transitive inheritance, ActiveRecord / Sequel / Packwerk. The workflow with the output each step prints: docs/RAILS.md.

Languages

23 languages and formats, detected rather than configured — enola looks for the markers in your tree and indexes whatever it finds, so a repository that is two languages is indexed as two without being told, and the boundary worth grading is usually the one between them.

Per language, exactly which construct becomes which fact — and what each extractor deliberately does not resolve, stated next to the capability: docs/extraction/. Every example on those pages is copied from a golden file the test suite asserts against.

Point it at a second repository and it links them into one graph — a web client's fetch() to the backend route that serves it, a mobile endpoint enum to that same route, a gRPC call site to the .proto service behind it — so an agent can answer if I change this endpoint, which screens break? by traversal instead of inference.


Latest engineering articles

Read our technical deep-dives on enola.tech/blog:


Connect & contribute

Pinned Loading

  1. enola enola Public

    Architecture intelligence for developers, coding agents, and CI - understand codebases, analyze change impact, and catch architectural regressions.

    C 201 15

Repositories

Showing 5 of 5 repositories

People

This organization has no public members. You must be a member to see who’s a part of this organization.

Top languages

Loading…

Most used topics

Loading…