diagram-drift
Detect drift between a Mermaid architecture diagram and the codebase it describes. (check parses graph/flowchart, scans definitions + import/call, flags missing-in-code / stale-edge / missing-in-diagram.)
- Stars
- 0
- Language
- Python
- Created
- Jul 30, 2026
- Updated
- Jul 30, 2026
Introduction
diagram-drift
Detect drift between a Mermaid architecture diagram and the codebase it describes.
架构图漂移检测器:给 Agent 一份 Mermaid 架构图(
graph/flowchart)和一个代码库,check会精准报告「图里画的节点代码里还有没有、图中断言的依赖关系代码里是否成立」。

Before / After
Before — An architecture diagram is decoration. Nobody re-checks it against the code, so it slowly lies: a deleted module is still drawn, an edge claims a dependency that no longer exists.
After — A precise drift report: which nodes in the diagram have no matching definition in code, which diagram edges the code doesn't actually honor, and which real modules the diagram forgot to draw.
What it does
check— parse a Mermaidgraph/flowchart, scan the codebase for definitions (class/def/module names) and import/call relationships, then classify every node and edge.report— re-render the lastDRIFT_REPORT.mdfrom the store.- Output —
DRIFT_REPORT.md(human) +drift-state.json(machine-readable, so an agent can read it directly). - Zero third-party dependencies — pure standard library; Python uses
ast, JS/TS/Go and other languages use regex heuristics. Nopip install.
Drift types
| Type | Meaning | Severity |
|---|---|---|
missing-in-code | A diagram node has no matching definition/module in the code | HIGH |
stale-edge | A diagram edge A → B where A does not import/call B | HIGH |
missing-in-diagram | A real top-level module is absent from the diagram | INFO |
ok | Consistent | — |
Install
Clone into your agent's skills directory. No pip install required.
Codex
git clone https://github.com/whaojie797-design/diagram-drift ~/.codex/skills/diagram-drift
Claude Code
git clone https://github.com/whaojie797-design/diagram-drift ~/.claude/skills/diagram-drift
Cursor
git clone https://github.com/whaojie797-design/diagram-drift ~/.cursor/skills/diagram-drift
Quick start
# 1. point at a diagram (a .md with a ```mermaid block, or a .mmd) and a codebase
python scripts/drift.py check --diagram arch.md --root ./src --store .driftstore
# 2. later, re-check after the code changed
python scripts/drift.py check --diagram arch.md --root ./src --store .driftstore
# 3. re-render the last report
python scripts/drift.py report --store .driftstore
--ignore dir1,dir2 skips extra directories on top of the built-in ignores
(node_modules, dist, tests, __pycache__, …).
Sample report (real)
$ python scripts/drift.py check --diagram arch.md --root code_drifted --store .ds
Parsed diagram: 5 nodes, 5 edges
[OK] node — Gateway
[OK] node — AuthService
[OK] node — BillingService
[HIGH] node — NotifyService — no definition or module matches 'Notify Service'
[OK] node — Database
[OK] edge — Gateway -> AuthService
[OK] edge — Gateway -> BillingService
[OK] edge — AuthService -> Database
[OK] edge — BillingService -> Database
[HIGH] edge — BillingService -> NotifyService — BillingService does not import/call NotifyService
[INFO] module — analytics — module 'analytics' exists in code but is absent from the diagram
5 nodes · 5 edges · 2 drift (HIGH) · 8 consistent
Against a codebase that still matches the diagram, the same command reports
0 drift (HIGH) · 10 consistent.
How it works
- Extract the diagram source (a fenced
```mermaidblock, or a rawgraph/flowchartstring). - Parse nodes and edges with a small Mermaid subset parser (square/round/
diamond/cylinder shapes,
-->,-.->,==>, labeled and&chains). - Walk the codebase, collecting definitions and per-module import/call tokens.
Python via
ast; other languages via regex. - For each node, check whether any of its id/label tokens matches a code
definition or module name. For each edge, check whether the source module
actually imports/calls the target. Cross-language name matching normalizes
case and separators (
AuthService≡auth_service). - Write
DRIFT_REPORT.md+drift-state.json.
Everything is deterministic; the test suite runs entirely against local
fixtures (tests/fixtures/code_clean vs code_drifted).
Limitations
- It matches on names and import/call tokens, not full data-flow. A node
whose name was renamed (but behavior preserved) is still flagged as
missing-in-code. - Edge validation is heuristic: it confirms the source module references the target module/identifier, not that the call is on the specific path drawn.
- Non-Python languages rely on regex; unusual import styles may be missed.
Extend
scanner.pyif you need deeper coverage for a specific language.
License
MIT © 2026 whaojie797-design