Airframe

Why Airframe

Agent-ready

Airframe was designed with a coding agent as a contributor from the start. A change a coding agent writes runs through exactly the same checks as a person's, and the approval that lets it merge comes from the account of a named person of the catalog who neither wrote nor committed it.

A coding agent's loop

  1. Skills teach the platform

    The platform-skills repository gives every coding agent that loads it the platform's patterns: where a change belongs, the catalog, a product's roots and the golden-path modules, naming, and the policy pack's rules with their messages. Four of the five skills ship examples that the policy pack, terraform validate or the catalog's lint must accept or refuse as the skill says, and the platform overview is checked for the paths it names. These checks run on every change to the skills, against the policy pack of the release the skills pin, and again when a new release is verified before it is permitted.

  2. Validate locally, as the merge request does

    airframe validate runs the merge request's validation on the laptop, without credentials or state: formatting, terraform validate, OpenTofu's validate and tflint where they are installed, and the policy pack on the Terraform roots, the pipeline file and the declared Dockerfiles. What needs the platform stays in the pipeline: the gate's checks, GitLab's secret detection, dependency scanning and static analysis, the application's build and tests, the plan, the pack's check of the plan and its price.

  3. Read the message, fix, validate again

    A failing rule names the resource and what is wrong with it, and many also say what to do instead, so the loop is short: write, validate, read the message, fix, validate again, then open the merge request. A warning does not fail the run; the skills tell a coding agent to fix it or to give its reason in the merge request.

  4. The same checks as everyone

    The merge request runs the same injected jobs and the same rules whoever wrote it; nothing in them depends on the author. By the convention the platform's instructions for a coding agent and its skills teach, a coding agent's commits carry a Generated-by trailer naming the agent and the model, and its merge requests carry the agent label. Nothing checks either yet.

  5. A named person approves

    GitLab's approval policy counts only the approval of a person the catalog names who neither wrote nor committed the change, and the gate approves only once the change's current owners have. A coding agent with an account of its own is named nowhere, so its approval never counts. One that works through a person's account is that person to GitLab: it cannot give the approval that counts on a change it wrote there, and nothing tells it apart from the person.

Try it

Follow a coding agent through one change. Every message below is what airframe validate printed for that file, at the platform release this site describes.

Step 1 of 4

The agent writes a bucket

Asked for an export bucket, the agent declares one with a single label. Validation fails before anything is pushed.

Denied
resource "google_storage_bucket" "exports" {
  name     = "exports"
  location = "US-CENTRAL1"
  labels   = { product = "orders" }
}
  • Denied naming.labels

    google_storage_bucket.exports: missing labels ["criticality", "domain", "env", "managed_by", "tenant"]

    Every resource carries the platform's labels, which record who manages it, the organization, domain and product it belongs to, its environment and its criticality.

  • Warning naming.raw-resource

    google_storage_bucket.exports: a raw google_storage_bucket in a product root needs a reason in the merge request (platform approval); compose the registry's modules where one covers it (skill airframe-naming)

    A resource the product declares itself, instead of composing a module, needs a reason in the merge request. The policy pack warns about it; the platform's approval of it is designed, and today a warning holds nothing back.

  • Warning naming.slug-prefix

    google_storage_bucket.exports: name "exports" does not start with the product's slug "orders" (docs/contracts.md 2; skill airframe-naming)

    A name the product writes itself starts with the product's slug, so it says where it belongs.

What makes it true

A skill says what the platform's checks do.
The platform-skills pipeline's skills:policy, skills:validate, skills:catalog and skills:references jobs check each skill's examples against the policy pack at the control-plane commit the skills pin, terraform validate and the catalog's lint, and check that every path a skill names exists; GitLab merges a change to the skills only when they pass. control-plane's release:check requires that pin to be the release's, and release:verify runs the same jobs at a new release's commits before it is permitted. Whether a coding agent loads a skill is up to the agent and its user.
The laptop runs the merge request's validation.
airframe validate (the platform's local validation script) runs the validate component's formatting, terraform validate and policy pack commands with no backend and no credentials; OpenTofu and tflint run only where they are installed. It reads the pack from the control-plane clone it is installed from, not from the release the product pins, and it does not run the catalog lint, the gate, the application's tests, the plan or its price.
A coding agent's work is labeled.
A convention, not a check: the instructions for a coding agent in the workspace and in the product template, and the airframe-platform skill, ask for a Generated-by trailer on every commit and the agent label on the merge request, and the platform's GitLab configuration defines the label. No job or rule checks either, so they record what a coding agent or its user declares.
Only a named person's approval lets a change merge.
The approval policy in the security-policies project lists its approvers by name, the catalog's active people with a GitLab account, and excludes the author and the committers; today, in every repository but security-policies, which holds the approval rules themselves, the gate's approval is required as well, and the gate counts only the approvals of the change's current owners, under the same exclusions. A coding agent with its own account is on neither list. One acting through a person's account or token is that person to GitLab, and nothing distinguishes the two.