The Anatomy

The client source of this site, parsed on every build. This tab says what the page measures and how to read it. The tree tab is the source as it sits on disk: every folder and file, and for each file the syntax walk, the definitions with their call edges, and the source itself.

Reading

A1This page is derived

This tab is the one thing on the page I wrote; it says how to read the rest. Every panel, every number and the whole tree tab come out of the build: it parsed every source file of the site's client, built the call graph, ran the diagnoses and laid every syntax node on a grid. The page renders that output by shape, which is what derived state on the methodology page asks of any state. The module's totals are the measurements, and the edges between its containers are A1·bthe import graph.

A1.1What the reader is seeing

A page about a system is derived from the system in the same build that renders it, or it is a claim. A page that describes a codebase is prose about the codebase, and prose has no mechanism that makes it wrong when the codebase changes.

An architecture page names three containers and the tree holds four, the fourth added the week after the page was written, and every reader of the page reasons about a tree that no longer exists. A description written by hand is a second copy of the tree, and a second copy disagrees with the first from the day one of them moves.

Publish the derivation and not a description of it, so the page can only be as wrong as the build that produced it. Read every number on this page as a measurement taken at build time. Open the tree tab to see the source as it sits on disk; open a file to see its walk, its definitions and its source. Where a number here disagrees with the tree you can read, the tree is right and this page is stale.

Pick any file on the tree tab and open the same file on disk. The definitions, the line count and the imports on the page match the file, or the page was not derived from it.

The page describes the client source the reader is looking at and nothing behind it. The tooling that produced it, the documents that govern it and the checks that gate it are not on this tree, so they are not on this page.

The measurements are the same ones the quality tooling reads: how many definitions the parser found, how many call edges it resolved between them, how many calls it could not resolve, and the diagnoses it ran. A call the parser cannot resolve is counted and never guessed, so the resolution rate is a measured fraction and not a hope.

The import graph folds every import a file makes to the container that owns the imported file, so an edge is a container reaching into another container, counted. The direction axis on the architecture page says which way those edges may run; this graph says which way they do.

B1The four parts, measured

A system is a graph on the architecture page names four parts, and each one is measured here. The components are the definitions, the relations are the call edges between them, the schema is the set of diagnoses the parser can run, and the propagation is the fan-in every definition carries. The shape of the whole is B1·astructure, and the order in which it runs is B1·blogical flow.

B1.1Components, relations, schema, propagation

Every definition carries an in-degree and an out-degree, and the two decide its flow class: an entry has callers and no callees, a leaf has callees and no callers, a relay has both, and an isolated definition has neither. The flow classes are counted per file, per folder and for the whole tree, so a container that is mostly leaves and a container that is mostly relays read differently before a single file is opened.

Definitions own what, code owns how is what the split between the two charts shows: the structure is what exists and how it is arranged, the logical flow is what calls what when it runs. Both are read from the same syntax trees, so they cannot disagree with each other, only with a tree that has moved since the build.

B1·astructure
flowchart LR
    n_root["root · 396 files"]
    n_configuration["configuration · 152 files"]
    n_core["core · 76 files"]
    n_domain["domain · 24 files"]
    n_presentation["presentation · 110 files"]
    n_runtime["runtime · 2 files"]
    n_types["types · 25 files"]
    n_root --> n_configuration
    n_root --> n_core
    n_root --> n_domain
    n_root --> n_presentation
    n_root --> n_runtime
    n_root --> n_types
    n_configuration_constants["constants · 28 files · infrastructure"]
    n_configuration_icons["icons · 27 files · infrastructure"]
    n_configuration_strings["strings · 97 files · product"]
    n_configuration --> n_configuration_constants
    n_configuration --> n_configuration_icons
    n_configuration --> n_configuration_strings
    n_core_analyzers["analyzers · 3 files · processing"]
    n_core_assets["assets · 22 files · infrastructure"]
    n_core_buses["buses · 1 files · infrastructure"]
    n_core_converters["converters · 5 files · processing"]
    n_core_factories["factories · 1 files · infrastructure"]
    n_core_ids["ids · 31 files · infrastructure"]
    n_core_loaders["loaders · 4 files · infrastructure"]
    n_core_matchers["matchers · 1 files · processing"]
    n_core_normalizers["normalizers · 2 files · processing"]
    n_core_observers["observers · 4 files · application"]
    n_core_predicates["predicates · 2 files · infrastructure"]
    n_core --> n_core_analyzers
    n_core --> n_core_assets
    n_core --> n_core_buses
    n_core --> n_core_converters
    n_core --> n_core_factories
    n_core --> n_core_ids
    n_core --> n_core_loaders
    n_core --> n_core_matchers
    n_core --> n_core_normalizers
    n_core --> n_core_observers
    n_core --> n_core_predicates
    n_domain_converters["converters · 19 files · processing"]
    n_domain_loaders["loaders · 3 files · infrastructure"]
    n_domain_registries["registries · 2 files · infrastructure"]
    n_domain --> n_domain_converters
    n_domain --> n_domain_loaders
    n_domain --> n_domain_registries
    n_presentation_components["components · 15 files · product"]
    n_presentation_effects["effects · 4 files · product"]
    n_presentation_records["records · 12 files · domain"]
    n_presentation_renderers["renderers · 29 files · product"]
    n_presentation_styles["styles · 30 files · product"]
    n_presentation_tokens["tokens · 5 files · product"]
    n_presentation_views["views · 11 files · product"]
    n_presentation_widgets["widgets · 4 files · product"]
    n_presentation --> n_presentation_components
    n_presentation --> n_presentation_effects
    n_presentation --> n_presentation_records
    n_presentation --> n_presentation_renderers
    n_presentation --> n_presentation_styles
    n_presentation --> n_presentation_tokens
    n_presentation --> n_presentation_views
    n_presentation --> n_presentation_widgets
    n_runtime_coordinators["coordinators · 1 files · application"]
    n_runtime_entrypoints["entrypoints · 1 files · runtime"]
    n_runtime --> n_runtime_coordinators
    n_runtime --> n_runtime_entrypoints

C1Containers on the spine

Every file on the tree tab carries its subject, its concern and, where the name declares one, its variant, read off the file name the way placement is a grammar parses it, and every concern is tagged to a layer of the layer spine. The layers the tree lands on are C1·athe layers, and what moves between the containers at runtime is C1·bdata flow.

C1.1Roles, slots and layers

A folder's role is read from its depth and its name: the first folder under the member is a container, a folder whose name is a concern folder is a concern, and anything between is a subject folder that exists only because two sets of one concern must not merge. A file whose name the grammar cannot parse carries no slots and no layer, and the page says so rather than guessing one.

The layer a file lands on is a derivation from its concern and never a fact somebody typed, which is why the same file shows the same layer on this page and in every check that reads the tree. A folder shows the layer of its concern, and a container shows none, because a container groups by axis and not by layer.

D1What the diagnoses found

The diagnoses are the schema applied to the graph: a call cycle, a definition nothing consumes, a definition declared twice, a file that reaches across too many concerns, and an import cycle between modules. What they found is D1·athe findings, and a zero there is a measured zero, the difference unknown is not pass draws. One concern folder's walk is a walk, so the reading below has something to read.

D1.1What the schema can say

Each diagnosis names the control whose absence lets the decay in, the way an anti-pattern is a decay path teaches, and carries the remedy that reverses it. A finding on this page lands on the file it names, in that file's record on the tree tab, so the reader can open the walk and the source the finding is about.

A diagnosis that runs and finds nothing is different from one that never ran, which is the honest gaps on the architecture page. The diagnoses here are the ones the parser runs on every build; a predicate the method calls for that this parser does not compute is declared absent on that page, never assumed clean here.

D1·athe findings
No anomalies. Every diagnosis ran over the whole tree and reported nothing: no call cycle, no import cycle, no dead definition, no duplicate, no reach across a concern. The graph is closed and cohesive.
D1·ba walk38 steps

Select a cell to read what it is.

E1Reading a walk

A walk lays every meaningful syntax node of a file on a hexagonal grid in the order the parser met them, so a file is a path the eye can follow: down when the code nests, up when it returns, sideways when it continues. The states are E1·athe legend: what declares, what calls, what writes, what reads, what branches and what merely holds structure.

E1.1States, arrows and cells

The arrows mark the direction every few steps, and a flagged cell carries the severity of the finding that flagged it. Every cell is a reference into the data the walk ships beside it, so the vector stays a shape and the text lives in a file the page reads by reference, the same way a code panel is cited from the prose.

Drag to pan, scroll to zoom, and select a cell to read what it is: the file and line, the syntax kind and the text. A folder's walk is its files in order, and a file's walk is that file alone, so the tree can be read at either scale. A walk shows syntax and never semantics; what a call resolves to is the call graph's to say, and the definitions beside each file say it.

E1·athe legend
declare: declare call: call write: write read: read control: control structure: structure