The check pipeline
What mainsdk check runs on every change, the five layers of code safety, and how a change earns the Main mark.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
A change reaches main only when every layer passes. Each layer catches what the one before it cannot. Failures go back to your agent with the fix, so you see the result, not the noise.
Five layers of code safety
The requirements describe five layers but name only four of them (rules, intent, outcomes, proof); "safe building blocks" below is our descriptive name for the first, and the official names may change.
flowchart LR ctx["main.context<br/>who, where, what data, what features"] l1["1. Safe building blocks<br/>contracts and types"] l2["2. Rule checks"] l3["3. Intent reviewers"] l4["4. Outcome checks<br/>locked flows, accessibility"] l5["5. Proof<br/>launch report, Main mark"] main(["main"]) l1 --> l2 --> l3 --> l4 --> l5 --> main ctx -.-> l1 & l2 & l3 & l4 & l5 l2 -- fail + fix --> agent["Your coding agent"] l3 -- fail + fix --> agent l4 -- fail + fix --> agent
| Layer | When it runs | What it catches | Example |
|---|---|---|---|
| 1. Safe building blocks | As the agent writes, in milliseconds | The unsafe version is impossible to write | email.marketing() won't compile without an unsubscribe link; data can't be queried without an owner scope |
| 2. Rule checks | As the agent writes, in milliseconds | Below-baseline code, secrets, raw fetch, bypassed chokepoints | MAIN-SECRET-0002 a literal key in app/lib/pay.ts |
| 3. Intent reviewers | On every change before main | Code that does something other than what was asked. Reviewers use a different model or prompt from the coding agent | Hosted reviewers are paid; your own agent is free |
| 4. Outcome checks | On every change before main | Broken locked flows, missing screen states, accessibility misses | Headless browser runs of locked flows at desktop and phone widths; WCAG 2.2 AA |
| 5. Proof | When a release passes | Nothing to catch: it records the result | Launch report and the signed Main mark, 2.4.1+main27 |
What check runs
mainsdk check runs every registered gate. Each interface registers its own gates through the runner, and check resolves and tests every overlay combination in use (for example market in with segment enterprise).
mainsdk check [--env <name>] [--json] [--sarif <file>] [--fail-on <severity>]It exits 0 when every gate passes, 1 when a gate fails and 2 on a usage or configuration error; see the check for flags and CI setup. The JSON output is versioned:
// mainsdk check --json
{ "version": 1, "project": "prj_01JC8Q…", "env": "prod", "passed": false,
"gates": [{ "id": "secrets", "passed": false, "findings": [
{ "code": "MAIN-SECRET-0002", "severity": "critical", "file": "app/lib/pay.ts", "line": 3,
"rule": "secrets.no_literal", "fix": "Move the key to secrets and use secret:STRIPE_KEY" } ] }] }--sarif writes SARIF 2.1.0 so code scanning shows findings inline. Some rules worth knowing:
| Code | Rule |
|---|---|
MAIN-CHECK-0026 | A local driver resolved in production |
MAIN-NET-0001 | Raw network use (another HTTP client or a socket) outside the SDK |
MAIN-CONFIG-0010 | A layer weakens main.org.yaml |
MAIN-POLICY-0004 | A repo policy weakens an org policy |
check also lists every raw() escape hatch and every beta or experimental interface you use.
The guarantees it holds
If it's on main:
- No secret is in the code or the browser bundle.
- Every endpoint checks who you are and what you're allowed to do.
- Every record is private unless you made it public.
- Every flow you locked still works, on desktop and phone.
- Every minor went through age and consent checks, where your context includes minors.
- Every marketing email can be unsubscribed from, and every SMS has a recorded opt-in.
- Nothing that tracks runs before consent, where your regions require it.
- Every screen handles loading, empty, error and timeout states.
- Every package exists, is maintained and has no known vulnerability.
- Every destructive action had a human approval.
- Every release can roll back.
Exceptions
An accepted finding lives in main.yaml with a rule, a reason, an owner and an expiry date. While it is open the mark reads "Main 27 · 1 exception", and the day after it expires check fails again. See the check.
Speed is a guardrail
Our target gate time is under 5 minutes. A gate that blocks wrongly or slowly gets switched off, so gate time and the false-positive rate (target under 5%) are watched as closely as safe merges.
Later
| What | Phase |
|---|---|
mainsdk assure: standards and industry packs, owners and deadlines, SARIF, CycloneDX, OSCAL | 2 |
| Eval suites for AI features as gates | 2 |
| Deploy admission on a required Main mark across an estate | 4 (Fleet) |
Next
- The check: flags, modes and running it in CI.
- Check codes: every rule the gates report.
- Security architecture: the threats each layer answers.
Was this page helpful?