ArchDogma
A catalog of real engineering failures. The scanner is just a way to find them in your code.
Linters see code. ArchDogma sees history × structure — and every finding comes with a receipt: a documented, sourced case of a real team paying for this exact pattern.
Where this sits
Claims below are checkable; sources linked. Corrections welcome via the
honesty-bug label.
| Tool | Import-graph contracts | Git history × structure | Findings linked to sourced real-world failures | Free for private code |
|---|---|---|---|---|
| import-linter | yes | no | no | yes |
| tach | yes | no | no | yes |
| pydeps | visualisation only | no | no | yes |
| CodeScene | partial | yes | no | no (OSS only; CLI needs a token) |
| repowise | no | yes | aggregate statistics, not per-finding sources | yes (AGPL) |
| ArchDogma | yes — history-priced | yes | yes — external cases fetch-verified; first-party cases labelled as such | yes (MIT) |
The Catalog
Programming has sacred rules. "Always test." "Use microservices." "No copy-paste." "Clean Architecture." Nobody tells you when these rules start strangling your system.
ArchDogma collects real postmortems — companies that followed a rule and paid for it. Not to say the rules are wrong. To say they have conditions.
Current catalog: 12 dogmas — 10 filled with sourced failure cases — and 22 candidates.
Browse the full catalog: DOGMAS.md
Or from the CLI:
pip install archdogma
# View all dogmas with their status and linked cases
archdogma dogmas
# Search for a specific pattern
archdogma search "microservices"
archdogma search "inheritance"
archdogma search "coverage"
# Get the whole argument for one entry — rule, origin, cases, when to break it
archdogma explain dry
archdogma explain circular-import # by detector tag
archdogma explain 4 # by number
archdogma explain dry --speak # spoken summary, same as probe --speak
Selected postmortems
Microservices for everything → Segment (2018) 140+ services, one per data destination. Routing logic duplicated 140 times. On-call couldn't hold the system in their head. Folded back into one monolithic destination service. Delivery reliability improved. → full case
DRY → the wrong abstraction (Sandi Metz, 2016) A shared function serving 2 callers grows flag parameters as callers diverge, until every change breaks someone. Metz's rule: prefer duplication over the wrong abstraction. (The catalog also carries a first-party case of ours — QuackNet's 14-flag ProbeConfig — labelled first-party, because our rules require the label where there is no external link.) → full case
TDD → "a dense jungle of service objects, command patterns, and worse" (DHH, 2014) Verbatim: "Test-first units leads to an overly complex web of intermediary objects and indirection in order to avoid doing anything that's 'slow'." A first-person renunciation by the named engineer — an essay, not an incident report, and the catalog labels it as exactly that. → full case
OOP inheritance → two years to unwind the Tony Hawk object hierarchy (Neversoft, 2007) The industry-standard deep game-object hierarchy became a blob across three shipped titles; Mick West's first-person account of refactoring it to components while shipping a game a year. → full case
The Scanner
Once you know which dogmas are in play, find them in your code:
# Probe one function — Trust Score, AST tags, linked dogmas
archdogma probe mymodule.py -f MyClass.process
# Scan functions and classes — CI-ready
archdogma scan src/
archdogma scan src/ --fail # exit 1 if any tag fires
# Analyse module structure and change history
archdogma modules src/
archdogma modules src/ --all --no-history
The scanner is secondary. The catalog is the point. If the catalog didn't have real postmortems, the scanner would just be another linter. The postmortems are what make a detected pattern meaningful: "here's who followed this rule and where it broke them."
Three tiers, three kinds of question
Tier 1 — one function or class. deep-nesting, long-function, god-function, too-many-params, if-on-parameter, magic-numbers, dynamic-magic, broad-except, mutable-default-arg, too-many-returns, god-class, deep-inheritance.
Tier 2 — the import graph. circular-import, hub-module, god-module, unstable-dependency. Questions that do not exist inside a single file: what does everything depend on, and do the dependencies point where the folder names claim they do.
Tier 3 — structure crossed with git log. load-bearing-wall, churn-hotspot, single-author-hub, temporal-coupling. Tier 2 knows that forty modules import core.py; Tier 3 knows nobody has changed it in three years. Neither fact is alarming alone. And temporal-coupling finds the pairs that keep changing together while neither imports the other — the relationship no graph can show you.
Tier 3 needs a git work tree. Outside one — a shallow clone, a tarball, no git — every Tier 3 detector goes silent and says so. A missing history is not evidence of a young file.
For agents and CI
--format json is the machine-readable surface, and it carries the catalog with it:
archdogma modules src/ --format json
Every tag reports the ids of the catalog entries that claim it. Those entries are emitted once at the top level with break_when, main_signal, and links to the postmortems:
{
"tags": [{"name": "circular-import", "dogmas": ["clean-architecture"]}],
"catalog": {
"entries": {
"clean-architecture": {
"break_when": ["Team smaller than 5 and single product — ..."],
"main_signal": "You spend more time writing mappers between layers ..."
}
}
}
}
That is the difference between a linter and this: god-module at line 1 is no more useful than C0301 line too long. A tag with the conditions under which its dogma stops working is something you can argue with.
Contracts — priced by history
Declare architecture rules in pyproject.toml; every violation carries the importing file's git history, because a layering breach in this quarter's churn-hotspot and one in a file untouched since 2023 are the same boolean and very different work items:
[[tool.archdogma.contracts]]
name = "core must not import web"
type = "forbidden" # forbidden | layers | independence
source = ["app.core"]
forbidden = ["app.web"]
archdogma contracts . # fail on any violation
archdogma contracts . --fail-only-active # report all, gate only violations
# in files changed in the last 90d
Contract semantics follow import-linter's (credit where due — it's the standard). What it can't do and this can: --fail-only-active still reports dormant violations — it gates the exit code, it never hides findings. And without usable git history every violation counts as active: unknown is not dormant.
Our own contracts are declared in this repo's pyproject.toml and checked in CI.
MCP server
pip install 'archdogma[mcp]'
archdogma mcp # stdio server for Claude Code, Cursor, any MCP client
Five tools, all local, no tokens, MIT: scan_functions, analyze_modules, explain_dogma, list_dogmas, and the one the others exist to support — check_before_refactor: an agent about to edit an unfamiliar file asks "what am I about to break?" and gets the answer from the import graph and the git history: who depends on it, when it last changed, whose knowledge it is, and what historically changes with it.
Claude Code config (.mcp.json):
{"mcpServers": {"archdogma": {"command": "archdogma", "args": ["mcp"]}}}
A Claude Code skill ships in integrations/claude-code/ — copy it into .claude/skills/ to teach the agent when to reach for these tools.
SARIF
archdogma scan src/ --format sarif
archdogma modules src/ --format sarif
SARIF 2.1.0 for code-scanning UIs and review platforms. Every result is level warning, deliberately: this tool ships signals with context, not severities, and inventing a severity scale would claim a precision the detectors do not have.
Install
pip install archdogma
Core pulls exactly two dependencies (click, pyyaml) — the analyzers
themselves are pure stdlib. Optional extras:
pip install 'archdogma[pretty]' # rich rendering for --pretty
pip install 'archdogma[voice]' # pyttsx3 TTS fallback — only needed on
# Windows; macOS (say) and Linux
# (espeak-ng) speak with no extra at all
Or from source:
git clone https://github.com/gaidar0yegor/ArchDogma
cd ArchDogma
pip install -e .
Why This Exists
90% of engineering is understanding old code. And that code is full of dogmas applied without context. "Always test" — gamified into 100% coverage with no assertions. "Microservices" — applied to a 3-person team building one product. "Clean Architecture" — 5 layers for a CRUD app.
The pattern is predictable: a good rule gets applied without its conditions. Nobody wrote down when it stops working. The postmortems exist to fix that.
Honesty rules
- Every postmortem has a source link, or is explicitly marked first-party /
source_url: null. - Built with heavy AI assistance — the commit trailers say so on purpose. Sources are re-verified by a human before releases, and
tools/verify_sources.pyre-checks every link so you don't have to trust either of us. - Every claim can be challenged via the
honesty-buglabel on GitHub. - The scanner produces verifiable AST signals. No "expert" numbers without evidence.
- If a detector doesn't exist yet, the catalog says so:
[NEED POSTMORTEMS].
Accessibility
Voice mode from day one:
archdogma probe mymodule.py -f my_function --speak
Sighted and blind engineers get the same information. Not "later" — from the start.
Contributing
What we need most: real postmortems. Which dogma was applied at your company, under what conditions, and what broke.
- Post-mortem sources — open an issue with
postmortemlabel - Blind/low-vision engineers — primary reviewers of voice mode
- Honesty bugs — if you see a claim without a source, open
honesty-bug
Source of truth for the catalog: catalog/dogmas.yaml. DOGMAS.md is auto-generated via archdogma render-catalog.
License
MIT. Fork it, improve it.
If your fork drops the honesty rules or voice mode — don't call it ArchDogma.
🦫
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file archdogma-0.6.0.tar.gz.
File metadata
- Download URL: archdogma-0.6.0.tar.gz
- Upload date:
- Size: 180.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0d566a1bab6956382e743cb684b46d4ae5075ca08ae88fb2bdc03707cc28ef5
|
|
| MD5 |
2ba13f62eba43ed9f958c0d21f3cc4e8
|
|
| BLAKE2b-256 |
e66fba385d64cb0f55eb6a2d65fb7dca567baf65551c6f1909c17fb8231f5954
|
Provenance
The following attestation bundles were made for archdogma-0.6.0.tar.gz:
Publisher:
publish.yml on gaidar0yegor/ArchDogma
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archdogma-0.6.0.tar.gz -
Subject digest:
e0d566a1bab6956382e743cb684b46d4ae5075ca08ae88fb2bdc03707cc28ef5 - Sigstore transparency entry: 2415486220
- Sigstore integration time:
-
Permalink:
gaidar0yegor/ArchDogma@842ce63734892e42573f87d47e745a4382ac9b68 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/gaidar0yegor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@842ce63734892e42573f87d47e745a4382ac9b68 -
Trigger Event:
push
-
Statement type:
File details
Details for the file archdogma-0.6.0-py3-none-any.whl.
File metadata
- Download URL: archdogma-0.6.0-py3-none-any.whl
- Upload date:
- Size: 111.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff67fa76a506673480a53e7a197ed35afbf893a15cbf6c1391d331c3c7ed2fbc
|
|
| MD5 |
855b9a911beb29e54944a82259cf344f
|
|
| BLAKE2b-256 |
88c0d27ada1d20c32a6c58c5604f4945d2ab426cda1d92499dd4342ab71dc23e
|
Provenance
The following attestation bundles were made for archdogma-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on gaidar0yegor/ArchDogma
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archdogma-0.6.0-py3-none-any.whl -
Subject digest:
ff67fa76a506673480a53e7a197ed35afbf893a15cbf6c1391d331c3c7ed2fbc - Sigstore transparency entry: 2415486331
- Sigstore integration time:
-
Permalink:
gaidar0yegor/ArchDogma@842ce63734892e42573f87d47e745a4382ac9b68 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/gaidar0yegor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@842ce63734892e42573f87d47e745a4382ac9b68 -
Trigger Event:
push
-
Statement type: