Documentation / Quality and governance

Quality contract

Quality rules live in a versioned file in the repository, not in the prompt, and apply equally to people and agents.

The quality contract is your project's .ai/contract.json file. It defines how much rigor the team requires: measurement thresholds, coverage, complexity, change size, protected paths and waivers.

It is applied by the engine gate, Git hooks, CI and agents. The result doesn't depend on who writes the code: a person, Yuli, Claude Code, Codex, Kiro or Antigravity.

If the file doesn't exist or isn't valid, Yuli uses the defaults (Business criticality). Every field is optional, so a partial contract also works.

Where to edit it

Open the Governance Center (right rail → More tools, or the command palette with Open the Governance Center) and go to the Contract tab.

When you save with Save and sign, Yuli records the change with your git config user.name. You can see every change in Contract history.

Criticality

Criticality selects a complete threshold profile. There are four levels:

Value in the file Label in Yuli When to use it
low Low Prototypes, internal tools, experiments.
business Business Business applications. This is the default.
regulated Regulated Systems subject to audit or regulation.
safety Safety-critical Software where a failure has serious consequences.

Profiles

Threshold Low Business Regulated Safety-critical
Acceptance score 80 90 92 95
Measurement rounds 2 3 4 5
Minimum coverage 50 % 70 % 80 % 90 %
Max. cognitive complexity 20 15 15 10
Max. cyclomatic complexity 15 10 10 8
Minimum mutation score 0 % 0 % 60 % 75 %
Files per change 60 40 25 15
Lines per change 2000 1000 600 400
Independent review No No Yes Yes
Block test tampering No Yes Yes Yes
Strict enforcement No No Yes Yes

You can override a specific threshold in gates. Only that field changes; the rest still comes from the profile. Block test tampering and Strict enforcement depend only on criticality and can't be overridden.

The contract's acceptance score and rounds override the local settings of the Measurement phase.

File structure

{
  "schemaVersion": 1,
  "criticality": "business",
  "gates": { "minCoverage": 75, "maxCyclomatic": null },
  "changeLimits": { "maxFiles": 40, "maxLines": 1000 },
  "protectedPaths": ["db/migrations/**"],
  "waivers": []
}
Field What it defines
criticality low, business, regulated or safety.
gates acceptanceScore, maxMeasureRounds, minCoverage, maxCognitive, maxCyclomatic, requireIndependentReview, minMutationScore. null takes the profile value.
changeLimits maxFiles and maxLines per change.
protectedPaths Extra globs, added to the default protected paths.
waivers Waivers with an expiry date.
architecture Layers (layers with name, paths, mayDependOn) and forbidCycles.
slos Service objectives: latencyP95Ms, availability or errorRate.
licensePolicy Allowed (allow) and forbidden (deny) licenses, by SPDX or by family, such as strong-copyleft.
reviewer Independent reviewer: requireOtherFamily, provider, model.
dataClassification Data patterns with their level: public, internal, confidential or restricted.
finops Monthly budget per service and its owner.

Change limits

The size of a change is measured with git diff --numstat. Lock files (package-lock.json, yarn.lock, Cargo.lock, go.sum and similar) count as files, but their lines don't.

Exceeding the limit blocks with strict enforcement (Regulated and Safety-critical). In the other profiles it's a warning.

Protected paths

An agent can't edit these files, even if asked to:

  • .ai/contract.json, .ai/quality.json and .ai/state/**
  • .claude/settings.json and .claude/settings.local.json
  • .githooks/**
  • .github/workflows/**, .gitlab-ci.yml and Jenkinsfile
  • CODEOWNERS and .github/CODEOWNERS

Matching is case-insensitive. Add your own paths in protectedPaths. A change to the contract saved from Yuli is recorded in the audit log and counts as approved.

Waivers

A waiver lets you skip a rule temporarily and with justification.

Field Contents
id Waiver identifier.
rule Rule being waived: secrets, protectedPaths, testIntegrity, a specific cheating type or *.
path Glob it applies to. Empty means any path.
reason Reason.
approvedBy Who approved it.
expires Expiry date, YYYY-MM-DD.
ticket Optional reference.

A waiver is valid through the expires date, inclusive. A missing or malformed date counts as expired. Once it expires, the rule applies again and the gate warns you.

In the interface, each waiver shows its status: Active, Expires soon, Expired or Invalid date.

testIntegrity waives every test-cheating detection at once. Use it with a narrow path and a near date.

Audit

Every save appends a line to .ai/state/contract-audit.jsonl with the date, the author, the SHA-256 hash and a summary (for example, “criticality business→regulated; waivers +1”).

The author is always a person: the name provided or your git config user.name. “Yuli” and “Yuli Code” are rejected as authors.

Next step