INW017 diagram-unknown-name¶
What it does¶
Opt-in, and a warning when on. Reads the Mermaid and PlantUML architecture diagrams in the files the diagrams key lists and reports a name in them that [tool.inwards] or the code doesn't know, on the diagram's own line. A whole-project run (inwards check without paths, or the Stop gate with stop-gate = "project") checks them all; the per-edit hook, inwards server, MCP check_files and inwards check FILE check a listed diagram when it is the file edited or named (where it runs).
A diagram counts only when it is a flowchart or graph that opens with a marker comment, before or right after the header:
%% inwards: layers: every node id is a layer name.%% inwards: contexts: every subgraph at the top level, and every node outside a subgraph, is a context name. The nodes inside a subgraph can have any id.
A layer or context whose name can't be a Mermaid id, such as a template's slices.domain or a name with a space, is named by a node with any id whose quoted label is one of its modules entries: slices_domain["shop.domain"]. A name that can be an id must be the id, so a typo in it is still reported.
In both kinds, a label in double quotes is a module prefix or a layer selector (shop.domain, shop.*.domain), and must match a module that exists. A label without quotes, or one with spaces, is a caption and isn't checked. A node with the class external (db:::external, or class db external) stands for something outside [tool.inwards], such as a database or a third-party API, and is skipped.
What is reported, once per name and diagram, at its first mention:
- a node or subgraph id that names no declared layer or context, with the closest declared name when it looks like a typo;
- a quoted label that matches no module, with the closest module prefix;
- a
diagramsentry that matches no file, on the entry in pyproject.toml.
Mermaid blocks without the marker are ordinary docs and are never read. The arrows are INW018's: it compares them with the layer order, depends-on and public.
Why is this bad¶
Teams draw their architecture in the README or a docs page, and GitHub, Zensical and most editors render Mermaid in Markdown. Nothing ties the drawing to the code: a layer gets renamed, a package moves, and the diagram keeps showing the old picture. New contributors, and agents that read the docs before they write code, then work from a map that is wrong. An agent asked to "follow the architecture in docs/architecture.md" will put code in a services layer that the config calls application.
[tool.inwards] stays the only source of truth (ADR-045): the diagram is checked against it and the code, never read as config. A finding means the picture drifted; the fix is to redraw it, or to ask the user whether the config should change.
Example¶
[tool.inwards]
diagrams = ["docs/*.mmd"]
layers = [
{ name = "domain", modules = ["shop.domain"] },
{ name = "application", modules = ["shop.application"] },
{ name = "infrastructure", modules = ["shop.infrastructure"] },
]
[tool.inwards.rules]
extend-select = ["INW017"]
A diagram that calls the infrastructure layer infra and misspells the domain package:
%% inwards: layers
flowchart LR
infra --> application --> domain["shop.domian"]
infra --> postgres[("Postgres")]:::external
docs/layers.mmd:3:3: INW017 (warning) Node "infra" in this layers diagram names no layer: the layers are "domain", "application" and "infrastructure".
fix: Rename "infra" or mark it :::external.
1. Rename the node to the layer it shows.
2. If it stands for something outside [tool.inwards] (a database, a third-party service), mark it infra:::external.
3. If the diagram is right and [tool.inwards] is missing it, ask the user; don't edit [tool.inwards] yourself.
docs: https://sircypkowskyy.github.io/inwards/rules/INW017/
docs/layers.mmd:3:29: INW017 (warning) "domain" is labelled "shop.domian" in this layers diagram, and no module matches "shop.domian".
fix: Change the label to "shop.domain".
Fixed: the node has the layer's name and the label the package's. The whole project passes:
%% inwards: layers
flowchart LR
infrastructure --> application --> domain["shop.domain"]
infrastructure --> postgres[("Postgres")]:::external
How it works¶
The reader is a hand-written line parser in src/core/src/diagram/; Mermaid's own parser needs a browser DOM. It reads the flowchart syntax the Mermaid docs describe:
- Where diagrams are. In a
.mmdor.mermaidfile, the whole file. In any other listed file, each fenced block whose info string ismermaid(backticks or tildes, as CommonMark reads them). YAML front matter and%%{init: ...}%%directives before the header are skipped. PlantUML component diagrams (.pumlfiles and fencedplantumlblocks, marked' inwards: layersor' inwards: contexts) go through their own reader into the same model; the diagrams guide lists what it reads, and the fix hints use PlantUML syntax for them ([db] <<external>>). - Nodes. An id of letters, digits,
_and inner hyphens (order-api), with any shape:[ ],( ),([ ]),[[ ]],[( )],(( )),((( ))),> ],{ },{{ }}, the parallelograms and trapezoids, and@{ shape: ..., label: "..." }. A label written as a Markdown string ("`text`") is a caption. - Links. Every kind, with text in them (
-- text -->) or after them (-->|text|), an edge id (e1@-->), longer links (--->), chains (a --> b --> c) and&(a & b --> c). The reader records which links are solid or thick arrows that point one way, which INW018 reads as "may import". - The rest.
subgraph id [title]andsubgraph id["title"]up toend, nested;class a,b name;:::nameafter a node;%%comments, on their own line or after a statement;;between statements.classDef,style,linkStyle,click,direction,accTitleandaccDescrare skipped.
A statement the reader can't follow stops being read where it stops making sense; what came before still counts. Nothing is reported for a line it can't read.
Whether a quoted label exists is decided like INW006's check of a layer prefix: a module equals it or lies under it, or the selector matches one. The modules are the first-party modules of the whole-project run, or, when one diagram is checked on its own (the hook, the editor, a named path), the Python files under the config root, listed but not read.
How to fix¶
- Rename the node or subgraph to the layer or context it shows, as
[tool.inwards]spells it. - Fix the label to the module prefix the node stands for, or drop the quotes to make it a caption.
- Mark a node that isn't part of the project
:::external. - If the diagram is right and the config is behind, ask the user to change
[tool.inwards]; an agent doesn't edit it.
Fix safety¶
No automatic fix (autofix: false). The finding says the diagram and the config disagree; only a person knows which one is right. Renaming a node changes docs only and is safe; changing [tool.inwards] changes what every rule checks.
Configuration¶
Severity warning, so docs drift doesn't block the Stop gate by default. Opt-in: turn it on with extend-select, and list the files in diagrams:
[tool.inwards]
diagrams = ["README.md", "docs/**/*.md", "docs/**/*.mmd"]
[tool.inwards.rules]
extend-select = ["INW017"]
severity = { INW017 = "error" } # optional: block on drift
The rule has no options of its own; [tool.inwards.rules.diagram-unknown-name] takes only modules, which has no effect, since a diagram isn't a module. A finding can't be suppressed inline: a diagram holds no Python comment, and a %% comment would be one more thing for the reader to ignore. Mark the node :::external or fix the name instead.
Known limitations¶
- Layer and context names that aren't Mermaid ids, such as
slices.domainfrom a template, can't be a node id; such a layer is found only through a quoted label that is exactly one of itsmodulesentries, and only when no other such layer lists the same entry. - Mermaid flowcharts and PlantUML component diagrams only.
C4Context,architecture-beta, class diagrams and other PlantUML diagram types aren't read; a marker on one is ignored. The PlantUML syntax Inwards reads is in the diagrams guide. - One line at a time. A statement split across lines, or a label with a
"inside it (Mermaid's#quot;), may be read in part. - A code edit doesn't check the diagrams. Editing a diagram runs the rule in the hook and the editor; a package renamed in the code reaches the drawing on the next whole-project run.
- Hidden directories (
.github/) and the directories every walk skips (virtualenvs,node_modules) aren't searched by a glob; name such a file without a wildcard.
References¶
- #344: the rule; #332: the design decision, recorded in ADR-045.
- Mermaid: Flowcharts syntax: node shapes, links, subgraphs, classes and comments.