unifold 0.3.6

Reasoning behind unifold#

Why the standard looks the way it does: where its parts come from, what it adds, and the established ideas that predict it. Nothing here is a rule; the rules are in the standard.

Where the parts come from#

Taken from What it is What unifold adopts What unifold does not replace
Ports and adapters; component models such as the WebAssembly Component Model, the Fuchsia component framework and TOSCA A manifest declares what a component offers and requires, and the level above routes it Capabilities and needs per unit, wiring in the parent, and a rule that every need is connected. Only names and one-line summaries are declared, in a file per folder (0002, 0022). The runtime: unifold wires nothing when the program runs
Module boundary checkers such as Tach Declared dependencies between modules, checked against imports Declared dependencies, in any language; a unit does not name its providers. Units are chosen by a person or an agent (0034). The check against imports: unifold reads no code (0047); use such a checker beside it
C4, Structurizr, LikeC4 One central architecture model with generated diagrams in zoom levels Diagrams that zoom from the whole to the parts, generated and never drawn: the same three at every unit with children, no fixed levels, no central model (0005, 0029). A model that cuts across the folder tree
arc42 A template for architecture documentation The blackbox and whitebox of the building block view, cut up and stored in the folder of each block; the concerns of the explanation files, one file per concern (0037). The questions arc42 asks
Diátaxis Four kinds of documentation The kinds as the folders of docs/; the explanation kind has fixed file names (0035). The way of writing each kind
Backstage catalog YAML beside code for a portal across repositories A YAML file beside the code that says what a folder is and what it depends on A catalogue across repositories; keep both
ADRs (MADR) Decision records The format, stored per unit with numbers local to the unit; agents propose, people accept (0007). An existing log: its records move to docs/decisions/ as they are
AGENTS.md Free-text instructions for agents One AGENTS.md per unit, generated: a pointer to the documents, the skills, the unit index. The why is in README.md (0036). The convention: agents still read AGENTS.md first
Agent Skills A format for how-to guides that agents load The format of docs/skills/: the how-to kind for people and agents alike, with generated stubs where agents search (0027). The format: a skill of a unit is a plain Agent Skill
Controlled language such as ASD-STE100 Rules for technical writing One term for one thing, the present tense, the main statement first, short files. The full rule set and its dictionary
Domain-driven design, SOLID, test-first design Where boundaries go Explained below, not enforced (0014, 0031). The practices themselves

What unifold adds#

The first is wiring by the parent with a completeness rule. A unit states needs and never providers; the nearest unit above must connect every need, with one line each, and nothing connects by an equal name. We know of no other project that combines a manifest per folder, needs that do not name the provider, wiring by the parent, a completeness check and generated diagrams; absence in a search is not proof.

The second is the pair of context file and direction rules (0003). Hierarchical documentation usually lets children inherit silently from parents, which makes a child impossible to understand alone. unifold keeps the hierarchy and makes the inheritance explicit in one file per unit, with a stamp that shows when a restatement is stale (0026).

The third is scenarios as checked declarations (0069). A story of the system is written as hops, each a call from a unit to a part of a contract, and the checker resolves every hop against the wiring and the contracts. A story that needs a connection nobody declared is an error; a connection that no story uses is a warning; and the sequence diagram is generated, so it cannot disagree with the map. Sequence diagrams exist in every architecture method; here they are derived from declarations that a tool checks, across levels of the tree.

Three principles#

  1. The folder is the unit. Units are folders of the real code layout, and a unit holds code. unifold adds no folders of its own except docs/. Something that several units share, such as a protocol definition, is a document in the references of the unit above them, which every side names as its contract.
  2. Knowledge points inward and downward. A unit knows its own insides and the interfaces of its direct children. It does not know its siblings or its users; what it wants from them is a need. This keeps a parent small and lets a child be understood alone.
  3. Declare once, generate the rest. Structure is declared in the manifests, and every picture, table and pointer is generated: structure is cheap to derive and expensive to keep correct by hand. Reasons are written, in README.md, the explanation files and the decisions, because they cannot be derived.

Ports and adapters#

Idea In unifold
A port that the application provides An entry of capabilities
A port that the application requires, in its own terms An entry of needs. It names the contract that it and its provider share.
Adapter A unit of kind adapter: the one unit that talks to one external system, a need of the root (0066)
Pure domain logic A unit of kind logic: no input or output, no memory between calls; time and randomness arrive as parameters, so its tests need no fake
Composition root The wiring of the parent
Test double The ## Fake of a contract: a replay of its examples, or a simplified behaviour with faults, defined where both sides see it; or another provider as a named alternative
Two adapters for one port Capabilities that name the same contract

A unit that holds rules of the domain names its needs in the words of the domain. If such a need is met behind a network or a device, an adapter unit stands in between (wiring). The three well-known kinds make this checkable: a logic unit reaches no need of the root, and a need of the root is reached only by adapters, unless it is a platform service such as a clock.

Domain-driven design#

Idea In unifold
Bounded context A unit with a glossary of its own, usually near the top of the tree
Ubiquitous language The glossary of that unit
Context map The generated diagrams; the wiring is the list of relationships
Published language The contract of a connection, a document both sides name; a language that many share lives in the references of the unit above them
Customer and supplier One contract for the connection: a change to it is a change for both sides, and the checker refuses a connection whose sides disagree
Shared kernel A contract in the references of the parent, named by several children
Anticorruption layer An adapter unit

SOLID#

Principle Where it shows
Single responsibility responsibility states the one thing the unit is responsible for, and secret the one piece of knowledge it hides (0067); ## Why gives the reasons. A responsibility that needs "and" to join unrelated things suggests a split.
Open for extension New behaviour arrives as a new unit or a new provider. The wiring changes; the users do not.
Substitution Every alternative meets all that the need expects.
Interface segregation Several narrow capabilities instead of one that every user depends on in full.
Dependency inversion A unit depends on its needs, which it states itself. It never names a provider.
Acyclic dependencies Children of one unit should not need each other in a circle.

Test first#

Why three ways in for agents#

A skill alone is not enough. In an evaluation by Vercel, agents did not call an available skill in 56 % of the cases and passed 53 % of the tasks; with a compact index in AGENTS.md they passed all of them (source). In another study, 58 % of the trials never called an available dependency-graph tool (CodeCompass). So there is a generated AGENTS.md with the index, a skill, and a tool that every agent with a shell can run.

What studies say about instruction files, and what unifold does with it:

None of these studies tested unifold. Whether declared and checked structure helps agents more than a well-kept root file is not measured.

What the principles do not decide#

They do not say how big a unit is, how deep the tree goes, or which folder is a unit. That stays a judgement. Fewer, well-chosen units are better than many: a unit costs attention every time its surroundings change.

This page as plain Markdown, and its source on GitHub.