Skip to content

Anthropic built Scion for itself. Carbon Forge is yours →

Carbon Forge
Menu

Guide

Landing rules: code owners kept in the record, with an AEGIS workflow as a gate

A CODEOWNERS file names reviewers, but the approval lives on a forge and stays attached to a change that may have moved since. Carbon Forge keeps the rule and the approvals in the record, bound to the exact change, and lets a workflow be one of the approvers.

Also in: Español, Português, 日本語, Deutsch, Français, 한국어, 简体中文, Italiano, हिन्दी

Disclosure: we build Carbon Forge, and AEGIS beside it, at 100monkeys.ai, so read this as a maker's account. This guide was drafted by one of our AI agents from the public docs, chiefly step 8 of Working in lanes, Source control settings, MCP tools catalog: Lanes, continued and Source control: how it is built and why, and reviewed by the company. The table, calls and refusal are the docs' own. Where the docs leave a question open, the last section says so.

Why keep the rule in the record

The docs give the reason in two sentences: "Landing rules are the code-owners rule kept in the record. The approvers a path needs are named on a page of the workspace, and each approval binds to the lane's composition hash, so review is the record's and not a forge's." Without that, "a landing can carry code no approver saw." One limit up front: "Carbon runs no review itself." It records who approved what; the reviewing is done by people and by the workflows you name.

Step 1. Protect the trunk

Rules are read only on a protected trunk. A workspace admin ticks Protect the trunk under Settings, Workspace, Source control, and optionally Protect pages and atoms too. An agent checks the setting with:

workspaces.get_settings {}
→ { "workspaceId": "…", "trunkProtected": true, "trunkProtectedEntities": false }

From then on "the trunk moves only by a lane's landing", and a direct write is refused with workspace <slug> protects its trunk: the trunk lands by lanes.land only; write on a lane.

Step 2. Write the .landing-rules page

Create a page at the reserved path .landing-rules whose first Markdown table is headed glob | approvers | gate. The docs' example:

| glob | approvers | gate |
| --- | --- | --- |
| app/src/billing/** | <user id>, <user id> | |
| docs/** | <user id> | docs-review |

Only a workspace admin writes this page, on the trunk or on a lane; anyone else is refused with The landing rules page .landing-rules is reserved: only a workspace admin writes it.

Step 3. Check that the server reads it as valid

The Landing rules section of the settings dialog reports <n> rules, valid., or names a malformed row with Every landing is refused until it is fixed. A row naming a non-member, or naming neither an approver nor a gate, is malformed. A broken page stops every landing, so check this before you rely on it.

Step 4. Do the work on a lane

Open a lane and write on it as Working in lanes shows. At the landing every path the lane touches is matched against each row: a page by its path, a moved page by both paths, a tree file as <tree path>/<entry path>.

Step 5. Read what the lane still needs

lanes.create { "label": "agent/7/fix-login" }
lanes.get { "label": "agent/7/fix-login" }
lanes.export { "lane": "agent/7/fix-login" }   // header line: # composition: <hash>
lanes.approve { "lane": "agent/7/fix-login" }

lanes.get lists who has approved, who is missing, and whether each gate is pending or satisfied. In the app, a lane's Overview shows the same: the rules it matches, approved n of m, and an approval from a gate marked "via gate <workflow>".

Step 6. Approve the exact change

A reviewer reads lanes.export, one unified diff headed by # composition: <hash>, and then calls lanes.approve. The approval binds to that hash, so "a reviewer who reads the export and approves at its # composition: value has approved exactly that change." Any later patch, resolution or trunk move that changes what would land changes the hash, and earlier approvals then count for nothing. Approve after the last change, not before.

Step 7. Let the AEGIS workflow approve as the gate

A gate is satisfied only by the workflow itself. The run's token is minted with tokens.mint_execution and the optional workflow argument set to the gate's name, 1 to 128 characters; the run then calls lanes.approve through that token. The match is exact, "case included". "A person's approval, and one given through a token minted without workflow, satisfies no gate." The execution token is a child of the caller's token, limited to one workspace, one tree path, one lane, a tool list and at most a day. With AEGIS by 100monkeys.ai, in beta, the gate is a workflow of your own: the row names it, and Carbon Forge only checks that a run of it approved.

Step 8. Land

lanes.land { "label": "agent/7/fix-login", "intent": "fix: accept magic links", "dry_run": true }
lanes.land { "label": "agent/7/fix-login", "intent": "fix: accept magic links" }

A landing short of approvals is refused whole, naming what is missing:

Lane <label> touches <path> under landing rule <glob> (line <n>), which needs approval from <user ids> and gate <name> at the lane's current composition. Approve with lanes.approve; nothing was written.

When it lands, the approvals it consumed, the gate's included, "follow its intent as Approved-by: lines", and the changeset is sealed like any other. Note that a dry_run landing does not check the rules; read lanes.get for that.

What the docs leave unanswered

Related guides

Keep the review in the record.