← Back to blog
Language July 6, 2026 by Javier Arancibia

The Language That Maintains Itself

The language that maintains itself

First it compiled itself. Now it triages its own issues, fixes them, reviews the fixes, and ships them — 104 merged pull requests in three days, with no human in the loop for the routine case.


machin is a language shaped for AI agents to write: no type annotations, one canonical declaration per line, compiled through C to a native binary. Its compiler is written in machin and compiles itself, and its concurrency is proven race-free by inference. This post is the next beat in that series: what happened when I handed the maintenance of the language to agents too.

Between July 4 and July 6, an autonomous fleet opened, verified, and merged 104 pull requests on the machin compiler repository. It closed all 40 documentation-gap issues that had been sitting in the tracker, added roughly sixty new compiler tests, and the repo's computed trust score went from 57/100 ("building") to 100/100 ("auto-merge ready") — a perfect ship rate over the last thirty runs. Releases kept cutting on schedule the whole time.

That's the headline. The honest version is more interesting, and it's the part worth writing down.

The pipeline

Every two minutes a scheduler picks the highest-scored open issue. A three-agent team — architect, dev, QA — works it in an isolated git worktree, commits, and opens a PR. Then two gates decide whether it lands, and neither gate is an LLM grading its own homework:

  • The intent gate compares the diff against the issue it claims to fix. Not "is this good code" — "is this the requested change."
  • A required CI check on a protected branch: build the compiler, run the full test suite, and compile-and-run every example in the repository. enforce_admins is on, so even the owner's own token cannot skip it.

Only when both pass does GitHub complete the merge. These gates aren't decorative. From a real run, the intent gate rejecting a PR whose diff wandered off-issue:

intent gate: failed — FAIL — the diff never touches docs/LANGUAGE.md's
Builtins table at all; instead it edits AGENTS.md, a changelog HTML page,
and selfhost/server.mfl, which is entirely unrelated work

And CI catching an agent-authored example that wasn't in the language's canonical form:

--- FAIL: TestExamplesAreCanonical
    examples/complex/json_get.mfl is not canonical:
      have "s := json(Todo{id:1,title:\"ship it\",done:false})"
      want "s:=json(Todo{id:1,title:\"ship it\",done:false})"

Both PRs sat safely open instead of landing broken. That's the whole design: agents propose, mechanisms decide.

Autonomy was engineered, not enabled

Here's what the launch posts never tell you: between "the config says run 24/7" and the first autonomously merged PR, I had to find and fix five real infrastructure bugs. None of them were model problems.

  • A stale objective_status: met field from an old experiment silently excluded the repo from the scheduler's query. Zero log lines. The fleet was "on" for nine hours and did nothing.
  • The worker's CLI auto-updated itself overnight and wiped its own OAuth credentials. Every agent spawned into Not logged in.
  • gh pr merge fails outright on a branch with required checks if CI hasn't finished yet — and CI always takes a minute longer than the agents. Nothing retried. PRs piled up open until the merge command learned --auto.
  • Deploying the fixed worker binary by copying it to the host did nothing: the worker self-updates from a published release channel and quietly reverted my patch, twice, before I found the real deploy path.
  • Two hard compiler issues I'd filed mid-stream never got the "skip me" label, so the fleet burned fifteen-minute runs failing to solve compiler internals it was never meant to touch.

Every one of these is a systems bug, not an AI bug. Autonomy is a distributed-systems problem wearing an AI costume.

The stress test the system gave itself

When the issue queue emptied, the scheduler fell back to self-picked work — "improve test coverage" — and the track record changed sharply: nine of the next ten PRs got stuck on failing CI.

I investigated all nine, in parallel, with disposable agents instructed to answer one question each: is this a bug in the new test, or a real bug the test caught? The verdict was unanimous and, honestly, better than I expected: all nine were test-authoring mistakes. Zero compiler bugs. An agent assumed min/max builtins exist (they never did). One expected an empty program to type-check (machin requires main). One called a CLI entry point that exits the process, killing the test binary mid-run. Two branches collided with themselves via stacked duplicate declarations.

Two readings, both earned. The gates held: not one bad test reached main. And the compiler survived adversarial scrutiny from its own maintenance fleet: sixty new tests probing edge cases found nothing wrong with the production code.

Trust, but verify with a repro

One episode matters more than all the metrics, so I'll end on it.

The fleet picked up a real memory-safety bug I'd filed: a closure literal passed to go could read freed memory once the spawning goroutine's arena was reclaimed. It shipped a fix, with a test, and the commit said Fixes #314. The test passed. CI was green. The issue auto-closed.

The original repro still corrupted, deterministically, on every run.

The agent's fix was half right — it stabilized the closure's environment struct and capture boxes, and its test proved exactly that half. But the data those boxes pointed at still lived in the dying goroutine's arena, and the test never covered the shape that triggers it. The agent's own test file even said so, in a comment: "a separate follow-on fix, out of scope here" — and then the PR claimed the fix anyway.

I only caught it because, before building anything on top, I re-ran the original reproduction. Reopened the issue, completed the fix properly, verified it the same way the bug was found — corrupted 3/3 before, clean 5/5 after, plus a thirty-way stress test — and shipped it in v0.107.0.

The rule that falls out of this is the most useful sentence in the post: an agent's green test proves the test. Only the repro proves the fix.

Where the human actually sits

Not in the loop — above it. My job across those three days was building the gates, fixing the five systems bugs, spot-auditing samples, unsticking the roughly one-in-five PRs the gates correctly held back during the worst patch, and re-running repros before trusting any "Fixed." The agents did the typing; the mechanisms did the deciding; I did the verifying.

That's the same thesis as every post in this series. Machin bets that rigor gets cheaper when the ceremony tax falls on machines instead of humans — a compiler that proves race-freedom because an agent can afford the analysis, a language that compiles itself because byte-exact oracles made the port tractable. Maintenance turned out to be the same shape: a language written by agents, in a language built for agents, maintained by agents — with the trust anchored in mechanisms a human can audit, not in any model's self-report.

The repo is public. Every PR, gate log, and reverted mistake in this post is in the history, receipts and all.


machin is open source at github.com/javimosch/machin. It's built by Javier Arancibia — the same engineering that goes into intrane.fr.