# configuration/strings/graph.strings.ts

> 160 lines of code and 8 definitions.

Tree: Site tree
Language: typescript
Layer: product
Canonical: https://banes-lab.com/anatomy/tree#file-configuration-strings-graph-strings-ts
Source text: https://banes-lab.com/assets/sources/source.9c2a5d17e0845892085e84db853596f218953ab316a5f8c5304c0371ca672d97.generated.txt

## Definitions

- `SYSTEM_SHAPE` (lexical_declaration, line 6)
- `MODEL_DIAGRAM` (lexical_declaration, line 9)
- `FRACTURE_DIAGRAM` (lexical_declaration, line 12)
- `DEPENDENCY_DIAGRAM` (lexical_declaration, line 15)
- `DECLARATION_DIAGRAM` (lexical_declaration, line 18)
- `GRAPH_SECTION` (lexical_declaration, line 21)
- `DEFINITION_SECTION` (lexical_declaration, line 95)
- `GRAPH_SECTIONS` (lexical_declaration, line 168, exported)

## Source

```typescript
import { DEFINITION_SECTION_ICON, GRAPH_SECTION_ICON } from "#configuration/icons/architecture.icons";
import { DEFINITION_SECTION_ID, GRAPH_SECTION_ID } from "#core/ids/architecture.ids";
import type { Section } from "#types/document.types";
import { TYPESCRIPT_LANGUAGE } from "#configuration/constants/code.constants";

const SYSTEM_SHAPE =
    'export interface Component {\n    readonly id: ComponentId;\n    readonly concern: Concern;\n    readonly layer: Layer;\n}\n\nexport interface Relation {\n    readonly from: ComponentId;\n    readonly to: ComponentId;\n    readonly kind: "imports" | "exports" | "registers" | "consumes" | "emits" | "subscribes" | "interfaces";\n}\n\nexport interface Schema {\n    readonly invariants: readonly Invariant[];\n    readonly evaluate: (graph: SystemGraph) => readonly Finding[];\n}\n\nexport interface Propagation {\n    readonly reaches: (change: ComponentId, graph: SystemGraph) => readonly ComponentId[];\n}\n\nexport interface SystemGraph {\n    readonly components: readonly Component[];\n    readonly relations: readonly Relation[];\n    readonly schema: Schema;\n    readonly propagation: Propagation;\n}\n\nexport const derivable = (graph: SystemGraph, described: SystemGraph): boolean =>\n    graph.schema.evaluate(described).length === 0;';

const MODEL_DIAGRAM =
    'flowchart TB\n    components["Components · the nodes"]\n    relations["Relations · the edges"]\n    schema["The evaluative schema · applied to the graph"]\n    propagation["The propagation topology · how a change travels"]\n    rest["The graph at rest · what the system is"]\n    motion["Propagation · the system in motion"]\n    healthy{"Is the behaviour derivable from the self-description?"}\n    yes["Healthy"]\n    fracture["A fracture · dual write, hidden side effect, schema drift, manual-only governance"]\n    components --> rest\n    relations --> rest\n    schema --> rest\n    propagation --> motion\n    rest --> healthy\n    motion --> healthy\n    healthy -- yes --> yes\n    healthy -- no --> fracture';

const FRACTURE_DIAGRAM =
    'flowchart LR\n    test{"Can the system observe this value in its own self-description?"}\n    dual["Dual write · one fact declared twice"]\n    hidden["Hidden side effect · a value nothing reads back"]\n    drift["Schema drift · a description the system cannot check"]\n    manual["Manual-only governance · a step the description does not contain"]\n    closed["Closed · one declaration, derived everywhere"]\n    test -- no --> dual\n    test -- no --> hidden\n    test -- no --> drift\n    test -- no --> manual\n    test -- yes --> closed';

const DEPENDENCY_DIAGRAM =
    'flowchart LR\n    subgraph domain["domain"]\n        model["order model"]\n        policy["pricing policy"]\n    end\n    subgraph application["application"]\n        coordinator["checkout coordinator"]\n        store["cart store"]\n    end\n    subgraph processing["processing"]\n        converter["order converter"]\n        validator["order validator"]\n    end\n    subgraph product["product"]\n        view["checkout view"]\n    end\n    view --> coordinator\n    coordinator --> store\n    coordinator --> converter\n    converter --> model\n    validator --> model\n    validator --> policy\n    coordinator --> validator\n    policy -. circular dependency .-> coordinator';

const DECLARATION_DIAGRAM =
    'flowchart LR\n    definition["A definition · what exists"]\n    code["Code · how it behaves"]\n    derived["A derivation · read from the definition"]\n    restated["A restatement · written twice"]\n    definition --> derived --> code\n    definition -. never .-> restated\n    restated -. disagrees the moment either copy moves .-> code';

const GRAPH_SECTION: Section = {
    icon: GRAPH_SECTION_ICON,
    id: GRAPH_SECTION_ID,
    intro: "This section covers the model the rest of the page evaluates, in which a system is a graph and a question about the system is a question about reach, answered by a walk over that graph. <cite>the four parts</cite> shows the parts of the model, <cite>one feature</cite> shows a walk over one feature, and <cite>the four fractures</cite> shows the test the model applies. The practice of the model for a tree is described in derived state on the methodology page.",
    subsections: [
        {
            blocks: [
                {
                    application:
                        "In practice, the components and the relation kinds are named, the schema is stated as invariants a walk can evaluate over the graph, and the way a change propagates is stated, so impact analysis is a traversal rather than a guess. Every value the system carries is then tested by asking whether the system can observe that value in its own self-description, and a value that fails the question is treated as a fracture.",
                    boundary:
                        "The model is a description of structure, and it says nothing about which components are good. A graph with clean edges and a bad decomposition is still a graph, and the decomposition is judged by the schema applied to it, never by the model that holds it.",
                    cause: "A system described in prose has parts that cannot be enumerated and relations that cannot be traversed, so every question about it is answered by recollection.",
                    decision:
                        "The graph is modelled before any part of it, rather than parts being assembled and the graph inferred afterwards.",
                    failureMode:
                        "A limit is declared in two places, a state is written by hand where nothing reads it back, a description goes stale beside the code it describes, and a step is performed manually. None of the four is recorded as a defect, because none of them has a name.",
                    kind: "lesson",
                    principle:
                        "For this reason a system is modelled as components, relations, an evaluative schema and a propagation topology, and it is healthy when its behaviour is derivable from its self-description.",
                    problem:
                        "Software is usually reasoned about as a pile of parts rather than as a graph, so neither the developer nor the model can say what a change reaches or what the system claims about itself.",
                    validation:
                        "To check this, pick a component and derive what a change to it reaches, from the graph alone. Then change it and observe what actually moved. The difference between the two sets is the part of the topology that was never modelled.",
                },
                { caption: "the four parts", kind: "mermaid", text: MODEL_DIAGRAM },
            ],
            title: "Components, relations, schema, propagation",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "Which modules a change touches is a walk over the dependency graph. Which of two components knows about the other is the direction of one edge. Whether the whole can be built in one pass is whether the graph is a directed acyclic graph, and a circular dependency is the one shape that makes the answer no.",
                },
                {
                    kind: "text",
                    text: "Traceability, from a requirement to the code that carries it and back, is a path. Modularity, loose coupling and high cohesion are each a statement about how many edges cross a boundary and how many stay inside it. A list can hold every one of those facts and can answer none of the questions, because a list has no edges to walk.",
                },
                { caption: "one feature", kind: "mermaid", text: DEPENDENCY_DIAGRAM },
            ],
            title: "Why a graph and not a list",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "Self-describing architecture is the property the health test names, and it is stronger than observability. An observable system can be watched from outside. A self-describing one carries its own description as data it can read, and introspection over that data answers the reach questions without running anything.",
                },
                {
                    kind: "text",
                    text: "The four fractures are the four ways a description and a behaviour come apart. A dual write is one fact declared twice, and it disagrees with itself the moment either copy moves. A hidden side effect is a value the system changes where nothing reads it back, so it can be wrong forever. Schema drift is a description the system cannot check against itself, so it is right only on the day it was written. Manual-only governance is a step the description does not contain, so the system behaves differently depending on who performs it.",
                },
                { caption: "the four fractures", kind: "mermaid", text: FRACTURE_DIAGRAM },
            ],
            title: "The four fractures",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "Take any system you already have and ask of each fact where it is declared and what reads that declaration. A port written in a manifest and again in a start script is a dual write. A feature toggle flipped by hand in a console is a hidden side effect. A document that names three services where the tree holds four is schema drift. A release checklist a developer walks is manual-only governance.",
                },
                {
                    kind: "text",
                    text: "None of the four is a bug in the ordinary sense. All four are fractures in the derivation, and each has the same repair, which is one declaration with every other appearance derived from it or deleted.",
                },
            ],
            title: "The example is the system you have",
        },
    ],
    title: "A system is a graph",
};

const DEFINITION_SECTION: Section = {
    icon: DEFINITION_SECTION_ICON,
    id: DEFINITION_SECTION_ID,
    intro: "This section covers the split between definitions and code. A registry declares what variants exist and the code discovers them, a schema declares what a record carries and the code validates against it, and a manifest declares what a module is for and the code derives its surface. The split runs through every fact a tree carries, as shown in <cite>derivation or restatement</cite> and typed in <cite>the model typed</cite>, and its practice is described in one home on the methodology page.",
    subsections: [
        {
            blocks: [
                {
                    application:
                        "In practice, every fact is assigned to the side that owns it. A fact about what exists goes into a definition the code reads, and the code derives the rest from it, such as the list of variants, the shape of a record and the surface of a module. Where a fact already has a definition, the copy in the code is deleted. Where the code holds a fact nothing declares, the declaration is written and the code derives the fact from it, because a fact that lives only in behaviour cannot be checked without running the behaviour.",
                    boundary:
                        "A definition declares what and never how. A schema that carries a validation routine, or a manifest that carries a build step, has crossed into code and gained a second implementation of something the code already does. The split holds only while each side stays on its own side.",
                    cause: "Restating a definition in code is cheaper than reading it at the moment of writing, and the cost only arrives when one of the two copies changes and the other keeps the old truth.",
                    decision:
                        "The definition is read at the site rather than restated there, even where reading costs more on the day.",
                    failureMode:
                        "A registry lists twelve variants, a switch in the composer handles eleven, and the twelfth exists everywhere except where it is dispatched, because the switch was a second declaration that was never recognised as one.",
                    kind: "lesson",
                    principle:
                        "For this reason definitions own what, code owns how, and a fact with two declarations and no derivation between them is a fracture.",
                    problem:
                        "Code that restates a definition looks complete on the day it is written and becomes a second truth the day the definition moves.",
                    validation:
                        "To check this, take any fact the system carries and count the places it is stated. The target is one statement plus derivations. Two statements with no edge between them will disagree, and the only open question is when the disagreement is noticed.",
                },
                { caption: "derivation or restatement", kind: "mermaid", text: DECLARATION_DIAGRAM },
            ],
            title: "One declaration, derived everywhere",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "The split is single source of truth stated for a whole system rather than for a database. Declarative configuration states what is wanted and leaves the how to whatever reads it. Manifest-based design puts what a module is for into data beside the module, so its surface is derived rather than described. Metadata-driven design lets the description drive the behaviour.",
                },
                {
                    kind: "text",
                    text: "Code as data is where the split pays off, because a definition that is data can be inspected, transformed, validated and generated from, while a definition that is code can only be run. The registry pattern with auto-discovery applies the same idea to variants. The registry declares that variants exist, the tree holds one file per variant, and a glob-resolvable tree lets the code find them without a list that must be edited when one is added.",
                },
                {
                    kind: "text",
                    text: "Convention over configuration is the complement. A convention is a definition too, written once as a rule the reader derives from rather than a value the reader looks up.",
                },
            ],
            title: "The patterns that keep the split",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "The graph model is what makes the split checkable. A declaration is a node, a derivation is an edge, and a fact with two nodes and no edge between them is the dual write in the graph's own terms. Written as a type, the model is small.",
                },
                {
                    kind: "text",
                    text: "A component carries an identity, a concern and a layer. A relation carries its two ends and a kind from a closed vocabulary, so a new relation kind is a vocabulary edit rather than a new field. The schema carries the invariants and one evaluation over the graph, and schema validation is that evaluation run over every record that claims the shape. Health is one derivation, in which the schema is evaluated against the system's description of itself, and an empty finding set means the system is healthy.",
                },
                { code: SYSTEM_SHAPE, kind: "code", language: TYPESCRIPT_LANGUAGE, title: "the model typed" },
            ],
            title: "The model as a type",
        },
        {
            blocks: [
                {
                    kind: "text",
                    text: "A definition may say a record has a name and a kind from a closed set. It may not say how the kind is checked, because checking is behaviour. A manifest may say a module publishes three entry points. It may not build them. Either crossing produces the same defect, a truth held in two places with no edge between them.",
                },
            ],
            title: "Where the line sits",
        },
    ],
    title: "Definitions own what, code owns how",
};

export const GRAPH_SECTIONS: readonly Section[] = [GRAPH_SECTION, DEFINITION_SECTION];
```
