Appearance
Meta-modeling
Most of your graph models your application — its components, the rules they must satisfy, the relations between them. Meta-modeling turns the same machinery on the graph's OWN rule files: the deterministic checks, rule documents, and definitions under the .yggdrasil/ directory. Map them into the graph and you can verify the rules the way you verify everything else — the rules reviewing the rules.
The motivating shape is a feedback loop: a requirements document names the check meant to enforce it, and a rule reads that check and judges whether it actually does what the requirement says.
It's allowed, and opt-in
Pointing a component's file mapping at a path under .yggdrasil/ is allowed — the only mapping restriction is that a mapped path can't escape the repository. And because the graph directory is excluded from the "uncovered files" scan, you can model a few rule files without the coverage check demanding you model the rest. Meta-modeling is partial by design.
Four ways a rule file reaches a reviewer
- Mapping — map the file to a component and it becomes a reviewed file there.
- Static reference — list it under a rule's
references:and its contents ride every prompt for that rule. References need no mapping and no relation. - Companion (per unit) — a
companion.mjshook returns a different file per unit, so each requirement document can pull in the specific check it names. A companion-returned file must be reachable from the reviewed component (its own files, a declared relation's target, an ancestor, or a descendant). - Deterministic read — a deterministic check may read a reachable rule file through its context object (same reachability rule as a companion).
References (2) need no graph wiring; companion (3) and deterministic reads (4) need the target reachable, which for a graph-directory file means mapping it and declaring a relation to its component.
Consequences — read before you map
Mapping rule files makes them first-class citizens, with the obligations that brings:
- The built-in relation check parses your mapped check code; a check that imports another component's code needs that relation declared, or it's refused.
- Every rule effective on the component now reviews those rule files too — choose the component's type deliberately and use conditional rules so a code rule doesn't fire on a Markdown rule file.
- A rule that reviews another rule means editing one re-checks both — keep the meta layer small and targeted.
- Never map the whole
.yggdrasil/directory. A broad glob would sweep in the committed verdict lock, which changes on every approval and would never settle. Map narrowly — name the specific rule files you mean.
Keeping the blast radius small
Map narrowly; attach the meta rule on the narrowest component that owns the files it judges, not a broad parent that would cascade everywhere; and use conditional rules to target exactly the units you mean. Rule ids can be nested in directories, so a meta layer can live under its own prefix and stay legible — see Aspects.