PRACTICAL GUIDE · PYTHON · CI
Check Python architecture boundaries in CI
A passing unit test does not tell you whether a Python module imported a forbidden dependency. This guide reproduces one finding using ArchKeel's published Shop fixture.
This exercise uses ArchKeel's main branch, tested on 29 October 2026 at commit 79a2296c. Main changes; results may differ at a later commit. You need Git, Python 3.11 or later and uv. Work in a disposable clone: the exercise edits a fixture.
1. Get the fixture and record its starting state
git clone --depth 1 --branch main https://github.com/rapiddweller/archkeel.git
cd archkeel
uv sync --locked
uv run --locked archkeel validate --root fixtures/F-architecture \
--baseline guide-baseline.json --write-baseline --jsonThe fixture's archkeel.toml scans shop. Its existing architecture contract forbids shop.render from depending on shop.store. The baseline records the starting findings. In our run validation exited 0, source observation was PASS and declared rules were UNKNOWN; a successful command is not proof that every rule is decided.
2. Introduce a forbidden import
In fixtures/F-architecture/shop/render/text.py, add this line after the existing import from shop.model.entities:
from shop.store.repository import OrderRepositoryThe import is an intentional example violation. The relevant contract rule already exists; do not change the contract to permit it.
3. Inspect the actual finding
uv run --locked archkeel report --root fixtures/F-architecture \
--only violations --rule DEP-RENDER-NO-STORE --json > finding.jsonIn our run the result included this finding (IDs are omitted):
shop/render/text.py:9
DEP-RENDER-NO-STORE: shop.render.text imports forbidden
shop.store.repository.OrderRepositoryreport writes the JSON snapshot and an HTML report under fixtures/F-architecture/test-artifacts/architecture/. It exited 0 even though declared_rules was FAIL: report generates evidence, it is not the CI gate. Read the verdicts and the filtered finding.
4. Check the baseline, then fix the import
uv run --locked archkeel validate --root fixtures/F-architecture \
--baseline guide-baseline.json --jsonWith the added import our run exited 2: the forbidden dependency and the changed component graph produced validation diagnostics, and the baseline recorded one new violation. A nonzero exit fails a shell-based CI step. Exit 1 is also possible for other baseline changes; exit 2 means diagnostics must be read.
Remove the added import and run the same commands again. Our baseline validation then exited 0, filtered_violations for this rule was empty, and the overall declared-rules result remained UNKNOWN. The correction clears this finding; it does not resolve unrelated unknowns or prove runtime behavior.
5. Run the same check in CI
For a repository with an approved contract and reviewed baseline, commit the baseline with the project and run validation from that project root. For this fixture the command is:
uv run --locked archkeel validate --root fixtures/F-architecture --baseline guide-baseline.jsonInstall uv on the runner and run uv sync --locked first. For your own repository, install or declare ArchKeel for the runner and change --root and the baseline path to match its layout. This baseline check rejects new violations and contract diagnostics; it does not make UNKNOWN into PASS. Review initial findings before recording a baseline. For candidate-change checks and published expectations, use the separate check protocol.
See what architecture checks found in two real refactorings → · Fixture and full contract