INW017 diagram-unknown-name¶
Co robi¶
Opt-in, a po włączeniu ostrzeżenie. Czyta diagramy architektury w Mermaid i PlantUML z plików, które wymienia klucz diagrams, i zgłasza nazwę, której nie zna [tool.inwards] albo kod, w linii samego diagramu. Wszystkie diagramy sprawdza uruchomienie dla całego projektu (inwards check bez ścieżek albo Stop gate z stop-gate = "project"); hook po edycji, inwards server, MCP check_files i inwards check FILE sprawdzają wymieniony diagram, gdy to on jest edytowanym albo podanym plikiem (gdzie działa).
Diagram się liczy tylko wtedy, gdy jest typu flowchart albo graph i zaczyna się od komentarza-znacznika, przed nagłówkiem albo zaraz po nim:
%% inwards: layers: każdy identyfikator węzła to nazwa warstwy.%% inwards: contexts: każdy subgraph na najwyższym poziomie i każdy węzeł poza subgraphem to nazwa kontekstu. Węzły wewnątrz subgraphu mogą mieć dowolne identyfikatory.
Warstwę albo kontekst, którego nazwa nie może być identyfikatorem Mermaid, na przykład slices.domain z szablonu albo nazwa ze spacją, nazywa węzeł o dowolnym identyfikatorze, którego etykieta w cudzysłowie jest jednym z jej wpisów modules: slices_domain["shop.domain"]. Nazwa, która może być identyfikatorem, musi nim być, więc literówka w niej dalej jest zgłaszana.
W obu rodzajach etykieta w cudzysłowie to prefiks modułu albo selektor warstwy (shop.domain, shop.*.domain) i musi pasować do istniejącego modułu. Etykieta bez cudzysłowu albo ze spacjami to podpis i nie jest sprawdzana. Węzeł z klasą external (db:::external albo class db external) oznacza coś spoza [tool.inwards], na przykład bazę danych albo zewnętrzne API, i jest pomijany.
Co jest zgłaszane, raz na nazwę i diagram, przy pierwszym wystąpieniu:
- identyfikator węzła albo subgraphu, który nie nazywa żadnej zadeklarowanej warstwy ani kontekstu, razem z najbliższą zadeklarowaną nazwą, gdy wygląda to na literówkę;
- etykieta w cudzysłowie, do której nie pasuje żaden moduł, razem z najbliższym prefiksem modułu;
- wpis
diagrams, do którego nie pasuje żaden plik, przy tym wpisie w pyproject.toml.
Bloki Mermaid bez znacznika to zwykła dokumentacja i nie są czytane. Strzałki należą do INW018: porównuje je z kolejnością warstw, depends-on i public.
Dlaczego to źle¶
Zespoły rysują swoją architekturę w README albo na stronie dokumentacji, a GitHub, Zensical i większość edytorów renderuje Mermaid w Markdownie. Nic nie wiąże rysunku z kodem: warstwa zmienia nazwę, pakiet się przenosi, a diagram dalej pokazuje stary obraz. Nowe osoby w projekcie i agenci, którzy czytają dokumentację przed pisaniem kodu, pracują wtedy z błędną mapą. Agent poproszony, żeby „trzymał się architektury z docs/architecture.md”, wstawi kod do warstwy services, którą konfiguracja nazywa application.
[tool.inwards] pozostaje jedynym źródłem prawdy (ADR-045): diagram jest sprawdzany względem niej i kodu, a nigdy nie jest czytany jako konfiguracja. Zgłoszenie znaczy, że rysunek się rozjechał; poprawka to przerysować go albo zapytać użytkownika, czy to konfiguracja powinna się zmienić.
Przykład¶
[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"]
Diagram, który nazywa warstwę infrastruktury infra i ma literówkę w pakiecie domeny:
%% 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".
Po poprawce węzeł ma nazwę warstwy, a etykieta nazwę pakietu. Cały projekt przechodzi:
%% inwards: layers
flowchart LR
infrastructure --> application --> domain["shop.domain"]
infrastructure --> postgres[("Postgres")]:::external
Jak działa¶
Czytnik to ręcznie napisany parser linii w src/core/src/diagram/; parser samego Mermaida potrzebuje DOM przeglądarki. Czyta składnię flowchartów opisaną w dokumentacji Mermaida:
- Gdzie są diagramy. W pliku
.mmdalbo.mermaidcały plik. W każdym innym wymienionym pliku każdy blok kodu, którego info string tomermaid(z backtickami albo tyldami, tak jak czyta je CommonMark). Front matter YAML i dyrektywy%%{init: ...}%%przed nagłówkiem są pomijane. Diagramy komponentów PlantUML (pliki.pumli bloki koduplantuml, oznaczone' inwards: layersalbo' inwards: contexts) czyta osobny czytnik do tego samego modelu; co czyta, opisuje przewodnik po diagramach, a wskazówki naprawy używają dla nich składni PlantUML ([db] <<external>>). - Węzły. Identyfikator z liter, cyfr,
_i myślników w środku (order-api), w dowolnym kształcie:[ ],( ),([ ]),[[ ]],[( )],(( )),((( ))),> ],{ },{{ }}, równoległoboki i trapezy oraz@{ shape: ..., label: "..." }. Etykieta zapisana jako napis Markdown ("`text`") to podpis. - Krawędzie. Wszystkie rodzaje, z tekstem w środku (
-- text -->) albo za nimi (-->|text|), z identyfikatorem krawędzi (e1@-->), dłuższe (--->), łańcuchy (a --> b --> c) i&(a & b --> c). Czytnik zapisuje, które krawędzie są ciągłymi albo pogrubionymi strzałkami w jedną stronę; INW018 czyta je jako „może importować”. - Reszta.
subgraph id [title]isubgraph id["title"]aż doend, także zagnieżdżone;class a,b name;:::nameza węzłem; komentarze%%w osobnej linii albo za instrukcją;;między instrukcjami.classDef,style,linkStyle,click,direction,accTitleiaccDescrsą pomijane.
Instrukcja, której czytnik nie potrafi śledzić, jest czytana tylko do miejsca, w którym przestaje mieć sens; to, co było przed nim, się liczy. Dla linii, której nie umie przeczytać, nic nie jest zgłaszane.
To, czy etykieta w cudzysłowie istnieje, rozstrzyga się tak jak w sprawdzeniu prefiksu warstwy przez INW006: jakiś moduł jest jej równy albo leży pod nią, albo selektor do jakiegoś pasuje. Moduły to moduły własne projektu z uruchomienia dla całego projektu, a gdy jeden diagram jest sprawdzany osobno (hook, edytor, podana ścieżka), pliki Pythona pod korzeniem konfiguracji, wylistowane, ale nie czytane.
Jak naprawić¶
- Zmień nazwę węzła albo subgraphu na warstwę lub kontekst, który pokazuje, zapisaną tak jak w
[tool.inwards]. - Popraw etykietę na prefiks modułu, który węzeł oznacza, albo usuń cudzysłów, żeby była podpisem.
- Oznacz węzeł, który nie należy do projektu, jako
:::external. - Jeśli diagram jest dobry, a konfiguracja nie nadąża, poproś użytkownika o zmianę
[tool.inwards]; agent jej nie edytuje.
Bezpieczeństwo poprawki¶
Bez automatycznej poprawki (autofix: false). Zgłoszenie mówi, że diagram i konfiguracja się nie zgadzają; tylko człowiek wie, które z nich ma rację. Zmiana nazwy węzła zmienia tylko dokumentację i jest bezpieczna; zmiana [tool.inwards] zmienia to, co sprawdza każda reguła.
Konfiguracja¶
Poziom: ostrzeżenie, więc rozjazd dokumentacji domyślnie nie blokuje Stop gate. Opt-in: włącz ją przez extend-select i wymień pliki w diagrams:
[tool.inwards]
diagrams = ["README.md", "docs/**/*.md", "docs/**/*.mmd"]
[tool.inwards.rules]
extend-select = ["INW017"]
severity = { INW017 = "error" } # optional: block on drift
Reguła nie ma własnych opcji; [tool.inwards.rules.diagram-unknown-name] przyjmuje tylko modules, które nic nie zmienia, bo diagram nie jest modułem. Zgłoszenia nie da się wyciszyć w linii: diagram nie ma komentarza Pythona, a komentarz %% byłby kolejną rzeczą, którą czytnik musiałby pomijać. Zamiast tego oznacz węzeł jako :::external albo popraw nazwę.
Znane ograniczenia¶
- Nazwy warstw i kontekstów, które nie są identyfikatorami Mermaid, na przykład
slices.domainz szablonu, nie mogą być identyfikatorem węzła; taka warstwa jest rozpoznawana tylko przez etykietę w cudzysłowie, która jest dokładnie jednym z jej wpisówmodules, i tylko wtedy, gdy żadna inna taka warstwa nie ma tego samego wpisu. - Tylko flowcharty Mermaid i diagramy komponentów PlantUML.
C4Context,architecture-beta, diagramy klas i inne rodzaje diagramów PlantUML nie są czytane; znacznik na takim diagramie jest pomijany. Składnię PlantUML, którą czyta Inwards, opisuje przewodnik po diagramach. - Linia po linii. Instrukcja rozbita na kilka linii albo etykieta z
"w środku (#quot;w Mermaid) może zostać przeczytana tylko w części. - Edycja kodu nie sprawdza diagramów. Edycja diagramu uruchamia regułę w hooku i w edytorze; pakiet przemianowany w kodzie dociera do rysunku przy następnym uruchomieniu dla całego projektu.
- Ukryte katalogi (
.github/) i katalogi, które pomija każde przejście po drzewie (virtualenvy,node_modules), nie są przeszukiwane przez glob; taki plik podaj bez symboli wieloznacznych.
Źródła¶
- #344: reguła; #332: decyzja projektowa, zapisana w ADR-045.
- Mermaid: Flowcharts syntax: kształty węzłów, krawędzie, subgraphy, klasy i komentarze.