1. Layered architecture enforced by import-linter¶
- Status: Superseded by ADR-0007
- Date: 2026-06-23
Context¶
The codebase grew organically and had at least one circular dependency
(llm ↔ enrichment). Without an enforced dependency direction, low-level
modules risk importing high-level ones, making the system hard to reason about,
test, and reuse.
Decision¶
Define explicit layers and enforce their dependency direction with
import-linter contracts in
pyproject.toml ([tool.importlinter]), run as a blocking CI gate
(lint-imports):
coreandconfigare the lowest layers and import nothing else inwarp.databaseimports no app/domain modules.catalogmust not depend onllm,enrichment,api, orintegration.schemaandutilsmust not depend onapiorintegration.
The llm ↔ enrichment runtime cycle was broken by importing TableSamples
under TYPE_CHECKING in llm/prompts.py.
Consequences¶
- Dependency direction is verifiable and regressions are caught in CI.
- New code must respect the contracts (see CONTRIBUTING).
- A few contracts are intentionally conservative; they can be tightened (e.g. a strict total ordering) as the architecture stabilizes.