Documentation › Concepts
governance.pxf + domains
governance.pxf is the file that tells Steward how to read your
repository. Every dashboard, every PR verdict, every contributor
reputation score eventually traces back to a decision encoded
here. Read this once and the rest of the product stops feeling
opinionated and starts feeling like it's executing your
opinions.
Where it lives
The file sits at .steward/governance.pxf on the repository's
default branch. Steward reads it from the default branch — not
from the PR head — so a PR can't change the rules it's evaluated
against (the rules change only when a separate PR amending
governance.pxf is merged).
Format is PXF, a typed, comment-friendly serialization that compiles to protobuf. We dogfood our own format here; if you've written protobuf or HCL you'll be at home in seconds.
The minimal file
domains: [
{ name: "everything", path_globs: ["**/*"], max_cyclomatic_complexity: 15 }
]
That's it — a single domain that catches every file in the repo with one structural gate. Most repos start here and add specifics as they bump into them — or skip the typing entirely: the governance editor's posture wizard writes a preset-pinned file from three questions (see "Presets" below).
Domains: the central idea
A domain is a named slice of your code that gets its own
evaluation rules. Every file in a PR maps to exactly one domain
(the first matching path_globs wins — see "glob ordering"
below). Domains let you say "the API package needs 80% test
coverage; the docs folder needs none of that."
domains: [
{ name: "api", path_globs: ["internal/api/**"], min_coverage: 0.80, approval_threshold: 2 }
{ name: "docs", path_globs: ["docs/**", "*.md"], min_coverage: 0.0, approval_threshold: 1 }
{ name: "rest", path_globs: ["**/*"], min_coverage: 0.60, approval_threshold: 1 }
]
Each domain carries a vector of thresholds (per
internal/judge/governance):
| Field | Purpose |
|---|---|
name |
Stable handle. Used in reputation scores, audit events, dashboard filters. Don't rename casually. |
path_globs |
Which files belong to this domain. Doublestar syntax (** matches multiple path segments). |
min_coverage |
Test-coverage floor (0.0–1.0). Coverage gate compares head-PR coverage to this. |
max_cyclomatic_complexity |
Per-function complexity ceiling. Caliper gate rejects functions above it. |
approval_threshold |
Reputation points the PR author needs in this domain before they can self-merge without an extra review. |
supermajority_ratio |
Used for cross-domain consensus when a PR touches multiple domains (ADR-004). |
criticality_multiplier |
Weights the domain's contribution to overall PR score. Boost it for security-sensitive areas. |
restricted |
Marks the domain as needing elevated approval. The dashboard surfaces a yellow banner. |
enforcement |
Per-domain override of the repo-wide enforcement mode — see "Enforcement modes" below. |
self_merge |
"never" disables the reputation-based skip entirely: every PR in this domain takes the review path, regardless of the author's standing (and regardless of restricted). Default ("by-reputation") is the threshold behavior above. |
Fields not set inherit Steward's defaults. You don't need to set all of them on day one.
Enforcement modes
Structural gates don't have to block. A top-level enforcement
sets the repo-wide mode, and each domain can override it:
enforcement = "warn" # repo-wide: advise, don't block
domains: [
{ name: "security", path_globs: ["internal/auth/**"], enforcement: "block" }
{ name: "rest", path_globs: ["**/*"] } # inherits "warn"
]
| Mode | What a violation does |
|---|---|
observe |
Recorded in the audit trail + dashboard only. No PR comment, never blocks. |
warn |
Advisory PR comment ("in block mode this PR would be rejected"). Never blocks. |
block |
Rejects the PR — the default, and the behavior of every file written before this field existed. |
When one gate result spans multiple domains, the strictest
resolved mode wins (block > warn > observe).
This is the adoption ramp: set real thresholds on day one, run
them in warn, watch the dashboard to see what would fail,
then flip to block once the numbers say the bar is fair.
Every structural gate honors the mode. Domain-attributed gates
(coverage, complexity, perf, Static Analysis Results Interchange
Format (SARIF)) resolve per-domain overrides; repo-global gates
(pinned dependencies, license allowlist, mission-drift,
alternatives) take the top-level mode, since a go.mod belongs
to no domain. In warn/observe the evaluation also keeps
going after a violation instead of stopping at the first failed
gate — one run surfaces everything that would block. The cla
gate keeps its own independent enforcement field, and the
escrow/reputation flow is not a structural gate.
Presets — start from a posture, own only your deltas
Instead of writing every section, a file can extend a version-pinned preset baked into Steward:
preset = "welcoming/v1"
manifesto {
mission = "Human-friendly text serialization for protobuf schemas."
}
founders: [
{ handle: "your-handle", reputation_seed: { "everything": 2000 } }
]
That's a complete, working governance.pxf: the preset supplies
the posture (real thresholds in repo-wide warn, the contributor
on-ramp, Developer Certificate of Origin (DCO) sign-off at
flag-only), and your file carries only what is yours — the
mission and your founder seed.
Three rules to know:
- Overrides are section-wholesale. Any top-level section
present in your file replaces the preset's section entirely —
restating
clawith two fields means the preset'sexempt_loginsare gone unless you restate them too. There is no field-level merging; partial merges plus proto defaults would make "did I override that or inherit it?" unanswerable. - Versions are immutable.
welcoming/v1will behave the same forever — a Steward upgrade can never silently move rules you pinned (the build fails if a released preset's bytes change). Improvements ship aswelcoming/v2; adopting one is a one-line change in your file, reviewed like any amendment. - Unknown names fail loudly at load, listing the presets your Steward build knows. Presets cannot reference presets.
Available today:
welcoming/v1— young projects optimizing for their first contributors: real thresholds in repo-widewarn, the contributor on-ramp, sign-off at flag-only.disciplined/v1— teams shipping internal code: gates block,self_merge = "never"in every domain (reputation never substitutes for review), pinned dependencies, no community ceremony.vendor-led/v1— company-backed open source: concentric domain rings (restricted staff territory, an open community playground), sign-off at block, supply-chain timelocks — and deliberately no amendment voting: rules stay the vendor's. Requires afoundersoverride (the wizard emits it) — the restricted rings need seeded reputation to function.constitutional/v1— established community projects: everything on, including amendment voting (75% of the top-15 reputation holders, 14-day window) and slashing. Also requires afoundersoverride; the 30-day decay dissolves the seed into a real handoff.
Every preset deliberately ships no manifesto — overrides are
wholesale, and the mission is yours; each preset's header
comments show the recommended manifesto block to pair with it.
Glob ordering matters
DomainForPath returns the first domain whose path_globs
match. So put your specific domains first, your catch-all last:
# good — specific first
domains: [
{ name: "auth", path_globs: ["internal/auth/**"], ... }
{ name: "rest", path_globs: ["**/*"], ... }
]
# bad — catch-all swallows everything
domains: [
{ name: "rest", path_globs: ["**/*"], ... }
{ name: "auth", path_globs: ["internal/auth/**"], ... } # unreachable
]
If you suspect a file is being assigned to the wrong domain, the fleet dashboard's per-PR view shows the resolved domain for every file in the diff.
Top-level sections beyond domains
domains is the most-edited section. Steward also reads:
| Section | What it controls |
|---|---|
manifesto |
Mission statement (used by the mission-drift gate), perf-regression thresholds, blocked-module globs. |
cla |
DCO requirement, CLA enforcement (block or flag), exempt logins, template path. |
sarif |
Whether SARIF reports get ingested as gate findings. |
caliper |
Whether the server-side complexity analyzer runs. |
decay |
Reputation decay half-life — how fast inactivity erodes contributor authority. |
escrow |
Sandbox-issue auto-generation (the contributor on-ramp). |
amendments |
The governance-of-governance: how many reputation-weighted votes amending governance.pxf itself requires. |
triage |
Issue auto-labeling (`priority/high |
welcome |
First-PR welcome surface (template, who to assign). |
The API reference lists every field; the Write your first governance.pxf guide walks through a real example for a small repo.
What Steward does with it on every PR
- Steward loads
governance.pxffrom the default branch. - The PR's changed files are bucketed into domains.
- Each domain's thresholds become the gates the PR has to clear.
- Per-PR evaluation scores each of the five dimensions
(see Evaluations + dimensions),
weighted by
criticality_multiplier. - The result lands in the PR comment + the fleet dashboard.
If governance.pxf is missing, malformed, or empty, Steward
falls back to a permissive baseline: every file goes into one
implicit rest domain, every gate is set to its built-in
default, and the dashboard surfaces a "no governance.pxf" badge
so you remember to write one.
Amendments — changing the rules
Changes to governance.pxf itself can be subject to a voting
rule (configured under amendments). Default-off: small repos
just merge the PR like any other change. Larger projects flip
on supermajority_ratio to require a fraction of top-N
reputation holders to approve an amendment before it lands.
This is the "governance-of-governance" hatch. You probably don't
need it on day one. Revisit when you have enough contributors
that any one merging a governance.pxf change feels coercive.
What's next
- Write your first governance.pxf — step-by-step for a real Go/JS/Python repo.
- Evaluations + dimensions — how the per-domain thresholds turn into a PR verdict.
- Gates: DCO, CLA, complexity — the
load-bearing gate semantics referenced from the
cla/sarif/calipersections above.
Steward