Cookbook fixtures
The cookbook is one tree with two halves, and every recipe in either is a fixture run by CI with the same commands a user runs. A recipe that is not run is prose, and prose rules do not hold (plan 0005 ยง 1.1).
| Folder | Holds | Runner | Plan |
|---|---|---|---|
guards/<slug>/ |
the guard catalogue: one recipe per guard, over a committed graph | guards/run.sh |
plan 0005 |
questions/<slug>/ |
one page per architecture question, over a small source repository the docs site's playground loads | questions/run.sh |
plan 0004, Step 5 |
Both runners run in the guards CI job; the docs site renders the question pages from their fixtures (ADR-0074). The rest of this page is the guard catalogue; questions/README.md describes a question fixture.
- Plan: plan 0005, Step 1
- Requirements: FR-RULE-01, FR-CFG-07, FR-REACH-01 (the question pages)
- Decisions: ADR-0004 (the graph shape), ADR-0005 (what conversion drops), ADR-0007 (no vacuous recipe), ADR-0021 (public commands only), ADR-0024 (a regenerated expectation is explained), ADR-0074 (the question pages)
A fixture
guards/<slug>/, where the slug is kebab-case and names the guard, not the rule:
| File | Required | Holds |
|---|---|---|
rulebearing.yaml |
yes | the recipe: each rule with comment (ending in a decision token), fix, severity and examples with at least one forbidden and one allowed edge |
graph.json |
yes | a small graph in dependency-cruiser's cruise-result shape, holding only the modules the recipe needs, with every module fact as the extractor writes it |
expected.json |
yes | summary.violations and summary.vacuousRules exactly as cruise -T json prints them |
README.md |
yes | what the graph holds and why, which extractor supplies each fact in a real run, and any difference from the cookbook export |
expanded.yaml |
when the recipe uses defines or a shorthand |
config expand's output |
converted/.dependency-cruiser.json, converted/dropped.txt |
for a dependency-layer recipe | config convert --to dependency-cruiser's output and its report of what it dropped |
budget.json |
for a ratchet recipe | the budget file |
negative/<case>/rulebearing.yaml, exit-code, optional graph.json |
when the recipe has a failure to prove | a configuration that must stop cruise with that exit code (ADR-0008) |
The graph makes every rule non-vacuous, so vacuousRules is empty, except in a recipe whose point is allowEmpty.
Running
cargo build --release
cookbook/guards/run.sh no-circular # one fixture
cookbook/guards/run.sh --all # every fixture, one line each
guards/run.sh lists the commands it runs. RB names another binary.
Adding a recipe
- Write
rulebearing.yaml,graph.jsonandREADME.md. - Run
RB_UPDATE_SNAPSHOTS=1 cookbook/guards/run.sh <slug>to writeexpected.json,expanded.yamlandconverted/. - Read what it wrote. The violations must be the ones the README says the graph holds, and nothing else.
- Run
cookbook/guards/run.sh <slug>without the variable.
A recipe that does not behave as the cookbook says is a finding. Correct the recipe in the fixture and say so in its README; the dated cookbook export in docs/artifacts/ is not edited. If the engine is wrong rather than the recipe, record the defect in plan 0005's status table against the plan that owns the engine.