아키텍처 · 그림은 남이 그린다

zzop 자신의 import 그래프, 상한 없이

Every file in this repository and every import between them — 1,624 nodes, 3,118 edges, nothing dropped. zzop emitted two NDJSON tables and rendered none of it; the drawing below is a viewer reading those tables, which is the whole point. Point the same command at your repository and you get the same two files.

zzop graph . --domain dep --format cosmograph-links > links.ndjson
zzop graph . --domain dep --format cosmograph-nodes > nodes.ndjson

스냅숏이다: 이 그림과 이 페이지의 모든 수치는 페이지를 재생성할 때마다 scripts/site-graph-data.mjs 가 다시 쓴다. 즉 그 재생성이 돌았던 트리를 설명한다. CI 가 이걸 걸어 두지 않았으므로 레포는 그 뒤로 움직였다. 지금 체크아웃에 대고 위 커맨드 둘을 다시 돌리는 것이 곧 재계수다.

Colour by
Size by
    위 줄은 그 커맨드가 stderr 에 찍는 것이다 — stdout 은 파싱 가능한 표로 남는다. 레이아웃은 미리 계산돼 고정돼 있으므로 이 그림은 언제 와도 같다.

    읽는 법

    Nodes are files, edges are imports
    Direction is importer → imported, the direction ir.dep already stores. Size is degree by default; switch it to fan-in to find what everything depends on, or fan-out to find what depends on everything.
    Left to right is the dependency direction
    A file's column is the longest chain of imports that reaches it, so the far left is what nothing in the repository imports and the far right is what everything ends up leaning on. Import cycles have no such depth — no member of a cycle sits above another — so each cycle collapses into a single column rather than being broken at an arbitrarily chosen edge. Rows group files by top-level area, which is why a domain reads as one body.
    Zoomed out you get areas, zoomed in you get files
    At a distance a dot per file is confetti, so the wide view draws one bubble per top-level area — sized by how many files it holds, with arrows carrying the import counts between areas. Zoom past that and the bubbles resolve into the files inside them. It is one drawing at two grains: the bubbles are placed from the very file positions they summarise, so nothing you see far out contradicts what you find close in.
    cases/ is deliberately grey
    It is a labelled defect benchmark — every file in it is intentionally wrong, scored against cases/EXPECTED.jsonc. It is not product code, so it recedes.
    The far-right block is the files nothing imports
    A file with no imports in either direction has no depth to measure, so putting it in a column would claim a rank the graph never gave it. There are 122 of them here, and they used to be scattered across the frame at whatever bearing the old force layout's starting spiral happened to give them — positions that looked like information and carried none. They now sit in a block of their own past the right edge, grouped by area, so their position says the only two things it honestly can: this file has no imports, and this is the area it belongs to. Nothing is hidden by the move — the census below still counts every node.

    Most of them are there for a reason that is not a defect: a runner calls them, so nothing imports them by definition — cargo [[test]] and build.rs targets, [[bin]] roots, npm bin and scripts entries, files a <script> tag loads, and the labelled benchmark trees under cases/. This picture draws one relation, imports, and the entry points of any project sit outside it. They are not drawn differently: deciding "is this a runner entry point?" needs a per-language convention table, and a wrongly coloured node does not announce that it is wrong. A sentence cannot be wrong that way.
    Nothing is truncated
    The mermaid format caps this domain at 40 nodes, because a flowchart with a thousand of them is a black square that looks like information. This lane is uncapped instead, on the grounds that a viewer with zoom does the job a cap does for a drawn picture.
    Your own graph goes somewhere better than this page
    These tables are a standard shape — source/target for links, an id plus styling columns for nodes — so they load into Cosmograph, Gephi or any force-graph library without conversion. See the usage guide.