Authoring checks (rules)¶
A rule is one checkable requirement — a code clause, a design standard, a firm convention. This page explains how rules are written, compiled, validated, and promoted so they become part of your workspace's canonical ruleset.
You usually don't write rules by hand
The fastest path is to ask the Setup agent ("Author a rule that checks…"). It drafts the rule, compiles it, runs it against your open model, and — once it looks right — promotes it. The mechanics below are what happens under the hood, and what to look at when you want to review or refine a rule yourself.
Two kinds of rule¶
| Kind | How it checks | Lives as |
|---|---|---|
| Deterministic | C# code that reads the model and decides pass/fail precisely | Test.cs |
| AI check | A prompt that reasons over model data / sheet evidence | prompt.md |
| Hybrid | Both — deterministic gate plus AI judgment | Test.cs + prompt.md |
Every rule also has a spec.yaml — its metadata: id, title, discipline, severity, category, and
the kind of test. A README.md captures the rationale.
How a deterministic rule works¶
A deterministic rule is a small C# class that implements VitruAI's rule contract: it exposes its
spec and an Evaluate(...) method that sweeps the model (rooms, elements, parameters, geometry) and
returns findings with a status and evidence.
Rules are read-only against your model by design. Before any rule compiles, it passes a safety check that rejects anything that could change your model or reach outside it — file system access, network calls, launching processes, or Revit document mutations (creating, deleting, or editing elements). A rule can read and report; it can't modify.
Sharing code between rules (shared libraries)¶
Many checks are the same mechanic with a different number. "Bedrooms must be at least 11 m²" and "kitchens must be at least 7 m²" both need the true floor area of a possibly L-shaped room — and that geometry is the hard part, not the threshold.
So the geometry is written once, as a library, and rules link it:
# qaqc/rules/bedroom-min-area/spec.yaml
id: bedroom-min-area
testKind: Deterministic
testClass: Firm.Rules.BedroomMinArea
uses: [room-geometry] # ← link the shared library
// qaqc/rules/bedroom-min-area/Test.cs
using Firm.Lib.RoomGeometry; // ← and call it
namespace Firm.Rules
{
public class BedroomMinArea : IRuleTest { /* … RoomGeometry.AreaM2(room) … */ }
}
A library is a folder under qaqc/lib/<library-id>/ holding a spec.yaml (its id and C# namespace),
its .cs source, and a README.md. Your rule and every library it names are compiled together as
one unit, which is what makes the using above resolve.
Two names have to be unique, and the reason is the same
Because everything compiles together, two rules cannot declare the same testClass, and
two libraries cannot declare the same namespace. If they do, the compiler sees one type
defined twice and one of the two checks stops running.
The fix is to qualify names rather than shorten them — Firm.Rules.BedroomMinArea, not
BedroomMinArea. Validation catches this before anything runs and tells you which other rule or
library already owns the name.
Editing a library re-runs every rule that uses it¶
Change a library and every rule linking it picks up the new code automatically the next time it runs — there is no version to bump and no stale copy to hunt down.
That cuts both ways — re-validate the dependents
A rule's evidence that it behaves correctly was gathered against the old geometry. Nothing stops a rule from running on new math with old validation, so when you change a library, re-run the rules that use it and confirm they still land the true/false-positive matrix below. This is author discipline, not an automatic gate.
Drafting a library¶
- Drafts:
qaqc/lib-proposals/<id>/— anyone with access can draft here. - Canonical:
qaqc/lib/<id>/— promoted libraries, maintainer-owned, listed inqaqc/lib/_index.yamlso agents can discover them.
A library can also live at the firm level rather than in one project. If a project defines a
library with the same id as a firm one, the project's copy wins for that project — that is how
you override firm geometry locally without touching the firm baseline or editing uses: in every
rule.
Author → compile → validate → promote¶
DRAFT Setup agent (or you) writes spec.yaml + Test.cs into rules-proposals/<id>/
│
COMPILE compile_csharp: safety pre-pass → compile → cached, ready to run
│ (rejections or compile errors come back so the draft can be fixed)
│
VALIDATE run it against the open model and inspect findings against the matrix:
│ • true positive — a real problem IS flagged, with actionable evidence
│ • true negative — a compliant element is NOT flagged
│ • false positive — a compliant element wrongly flagged (the trust-killer)
│ • false negative — a real problem silently passed
│
PROMOTE once it behaves, the Setup agent moves it rules-proposals/ → rules/ (canonical)
and updates the discipline index so the Coordinator routes to it
Running a rule while authoring vs. a stored rule¶
- A freshly compiled draft is run by its compiled handle — used during authoring to iterate quickly in the current session.
- A stored (promoted) rule is run by its rule id from the workspace. This is what the
Coordinator and specialists use during a normal check; it reads the rule's definition from
rules/and runs it.
Either way, findings are captured and written to the run's report (see Concepts → Reports).
Validating a rule ("tests")¶
There is no separate unit-test framework — validation is empirical. You run the rule against a real model (ideally one with known good and known bad cases) and confirm it lands the true/false-positive/negative matrix above. A rule that produces false positives is the most damaging, because it erodes trust in every other result — so the bar for promotion is "no false positives on the validation model, real problems caught with actionable evidence."
The rule's README.md is where that reasoning is recorded, so a reviewer can see why the rule is
trusted, not just that it passed.
Where rules live¶
- Drafts:
projects/<project>/qaqc/rules-proposals/<id>/— anyone with access can author here. - Canonical:
projects/<project>/qaqc/rules/<id>/— promoted, active rules. The Setup agent owns promotion so the discipline index stays consistent (see Working with workspaces).
See also¶
- Agents, tooling & delegation — the Setup agent authors rules; specialists run them.
- Working with workspaces — where rules and the discipline index live.
- Concepts — findings, statuses, and how reports are produced.