Documentation · the schema

The schema an IDD graph follows

A graph is a directory in a git repository: one configuration file, a folder per register, and one small file per item. Everything the method enforces is a property of those files that a command can check.

A project on disk

The configuration file, throughline.toml, declares the project's own schema: which item types exist and which are roots, which link types carry justification, which statuses an item may hold and how they may move, and which attributes each type carries. Each register is a folder that owns a prefix such as REQ or TEST and hands out sequential numbers. This site's own graph looks like this:

idd/
├── throughline.toml          # the schema: types, roots, links, statuses, rules
├── vision/INT-0001.yml …     # intents, the roots
├── non-goals/NG-0001.yml …   # scope deliberately excluded
├── requirements/REQ-0001.yml …
├── nonfunctional/NFR-0001.yml …
├── risks/RISK-0001.yml …
└── tests/TEST-0001.yml …     # one or more per requirement

Nothing is generated and nothing is hidden: the files are the product, a reviewer reads them in a pull request, and a merge conflict on a requirement is an ordinary git conflict.

An item

An item is one YAML file named after its identifier. The fields that matter:

FieldWhat it is
uidPermanent and position-independent: never renumbered, never reused. Deleting an item leaves a tombstone, so a reference to it can still be understood.
typeOne of the types the schema declares: here intent, non_goal, requirement, nfr, risk, test.
statusWhere the item is in its life; see below.
title, textThe obligation, in the fewest words that still bind.
rationaleThe decision taken and the alternatives rejected, and who bears the cost of the obligation.
normativeWhether the item binds. A change to normative content changes the item's fingerprint, which is what makes a signature stale and a dependent link suspect.
attrsAttributes the schema declares for the type: here origin (human, ai or hybrid), priority, and disclosure, which gates what the splash publishes in its provenance mode.
linksTyped, directed edges to other items, each optionally carrying a stamp: the target's fingerprint when the link was last confirmed.

A human's ratification is recorded on the item too: who signed, when, and a fingerprint of exactly what they signed. If the normative content moves afterwards, the record no longer reproduces the fingerprint and the check reports it.

Roots and grounding

Some types are roots and may exist ungrounded: they are the why. In the default schema they are intent, business_need, risk, constraint, assumption and non_goal. Every other item must reach a root through a chain of grounding links: derives_from, implements, mitigates or verifies. Those links form a directed acyclic graph; circular justification is rejected.

A non_goal is a root but not a delivery root. It records scope deliberately left out, the thing a person points at to refuse a category of proposed work, so nothing has to derive from it and it is never reported as unserved. The tool shows non-goals to agents and reviewers; it never tries to detect an item that violates one, because that judgement stays with a person.

Coverage runs the other way too. This site's schema declares that every live requirement needs an incoming verifies link from a test, so a requirement nobody has said how to check is reported.

Statuses and who moves them

A project declares its own status words and the moves between them. What the tool needs is a handful of roles that those words play: the status an item is born in, the one that means proposed by a machine and awaiting a person, the one that means ratified, and the ones that mean suspect, invalidated and deleted. This site uses:

StatusMeaning here
draftBorn here when a person creates an item: specified, not yet agreed or built.
proposedBorn here when the item's origin is ai or hybrid. Awaits a named human; an error under the strict check.
approved, ratifiedAgreed. ratified carries a named person's signature over the exact wording.
implemented, verifiedBuilt; and shown to be built by its verifying tests.
suspectSomething this item depends on changed or was invalidated; it must be read again.
deferred, rejected, deletedParked; refused; tombstoned. A deleted item's file stays, so its identifier is never reused.

Every move is validated against the declared transitions, so an item cannot skip from proposed to verified, and every live status keeps a route back to ratified, so scope parked without a signature can still be put forward.

Links

Link types are declared by the project. The ones in use across this estate: derives_from, implements, mitigates and verifies carry justification; refines, relates, assumes and satisfies do not. satisfies is how a local item claims a clause of a standard it has composed, such as wcag:SR-0046: the splash's signposts satisfy a WCAG clause on link purpose, and that claim is in the graph rather than in a spreadsheet beside it.

A link may carry a stamp of its target's fingerprint. When the target's normative content changes, the stamp no longer matches and the link is reported suspect: the item at this end was confirmed against wording that no longer exists. Invalidating an assumption cascades suspect across everything that depended on it, which is the blast radius of a bad assumption made visible.

What the check enforces

tl check validates the whole graph and exits with a stable code: 0 when sound, 1 when there are findings at error severity, 2 on a usage error. Each rule's severity is the project's to set, and --strict raises every warning to an error for CI. The rules:

RuleMeaning
orphanA non-root item with no grounding chain to a root.
unserved-rootA delivery root nothing derives from or mitigates.
grounding-cycleCircular justification.
dangling-link, deleted-link-targetA link to a missing or tombstoned item.
uid-grammar, uid-collision, uid-filenameA malformed identifier, one identifier in two places after a merge, or a file not named after its item.
schemaA missing required attribute or a value outside its enumeration.
suspect-link, unreviewedA target changed since the link was confirmed; content changed since the item was last reviewed.
unratifiedAn AI-origin item still proposed.
ambiguousFlagged ambiguous; blocked from ratification until clarified.
ratified-content-mismatchThe content a signature was recorded over no longer reproduces its fingerprint.
coverageA declared coverage rule, such as every requirement needing a verifying test, is unmet.
unpublishedA normative item appears in no published document.

Composing other graphs

A project may adopt requirements that live in another graph, a published standard, a house style, a sibling requirement set, by reference rather than by copy. It declares each one under a namespace it chooses:

[[sources]]
namespace = "wcag"
url = "https://github.com/rhodium-org/throughline-wcag"
ref = "v2.2.3"          # a git tag pins the edition

A borrowed clause is cited as wcag:SR-0046. The check composes the project and its sources, and the sources those sources declare, into one graph under the project's schema and validates it as one. Imported items keep their own identifiers, so the same SR-0001 may exist in two sources without collision, and the composer controls the namespaces, so renaming one is a local change. Sources are read-only and fetched once into a cache. The catalogue lists every public source and the block that adopts it.

Documents and interchange

A document is prose that surrounds marked regions the tool fills from the graph: a table of requirements, a traceability matrix, a count. tl docs renders them in place and tl docs --check fails CI when a document has drifted from the graph it describes. tl dump exports a whole project as one documented JSON structure, which is the sanctioned surface for anything else that wants to read a graph; the splash's provenance mode, the catalogue and the browser tools all read that rather than the files.