Episode 00Reference

The Authority Gate

The authority model this estate runs on, the five things that turned out to be broken when I tested it by building this site, and the one I described wrongly.

Published

An AI agent can open a pull request against a production repository. In a regulated business three questions follow immediately, and most teams cannot answer any of them.

  • What was the agent permitted to do? Not what it was able to do. What it held authority to do.
  • What did it actually do, and under whose authority? A chat log is not evidence.
  • Is the output still as good as it was last month? A model change or a prompt change can lower quality silently.

This is the model I use to answer them. It runs across a twelve-repository estate.

Then I tested it by building this site through it, and five parts of it turned out to be broken. Those are in the second half, because a reference architecture that quietly fixes its own errors is the thing this document exists to argue against.

Authority is a predicate, not a policy document

Every artefact carries an autonomy_tier. The tier decides one thing: whether AI may merge to the canonical corpus. It never restricts drafting.

Tier Meaning May draft May merge
1 Internal. Tooling, process, private surfaces Yes Yes
2 Operator-adjacent. Affects how the business runs Yes No
3 Regulated or customer-facing. Payout maths, RNG, KYC, AML Yes No

A transition usually touches more than one artefact, so the effective tier is computed rather than read:

effectiveTier = max(source.tier, target.tier, domain.tier)

A missing tier is treated as Tier 3. That is deliberate rejection bias: a gap must stop the agent, never release it.

The gate itself is nine words.

export function mayAutoMerge(effectiveTier: number): boolean {
  return effectiveTier === 1
}

Governance fails when it lives in prose that each new feature reinterprets. Here it lives in one predicate every transition calls, and a reviewer reads the whole rule in five seconds.

The boundary is the merge, not the commit

An agent may commit to a branch at any tier, including Tier 3. Corpus state changes only when authority permits. A draft is a proposal, not history.

That distinction is what makes the model usable. Agents get to do the work; humans keep the decisions that carry consequence.

Two records, and only one is history

Most agent systems keep a log. A log answers “what happened recently”. An auditor asks “what happened, in what order, on whose authority, and can you prove nothing was removed”. Those need different records.

Audit ledger Run state
Role Permanent system of record Live, resumable progress
Shape Append-only, one line per terminal outcome Mutable, one file per run
Lifetime Never pruned, never rewritten Deleted once the run cannot resume
On conflict Authoritative Working copy

They join on a run identifier, so a whole run is reconstructable from the permanent ledger alone and run state never has to be kept for history’s sake.

Evaluate the one step that can degrade unseen

A lifecycle transition runs as six hops: compose, draft, create, gate, merge, sync. Five are ordinary code. Exactly one calls a model.

That asymmetry is the design. Deterministic hops fail loudly. The drafting hop is the only place output can get quietly worse while every test still passes, so it is the only place that earns a regression gate.

The evaluator returns one of four verdicts, and two of them are neither pass nor fail:

Verdict Effect
pass Both layers passed on a covered stage
regression Withholds a Tier 1 merge
uncovered No golden input exists. Reported honestly, never counted as a pass
could-not-run The harness itself failed. Never disguised as a pass

Most harnesses collapse “we checked and it was fine” with “we had nothing to check against”. Keeping them separate means an operator always knows which one they are looking at.

It escalates and never loosens. A regression can withhold a merge the tier permitted. No verdict can release a merge the tier refused.


What building this site found

The claims above were true as designs. Here is what happened when I made them carry real work.

1. The gate that could never fail

The canonical state checkers ran in CI on every pull request. They never ran at all.

The step resolved a path from a repository variable that was never defined, so the command became /runtime-adapters/... and exited MODULE_NOT_FOUND every single time. It carried continue-on-error: true, so the job went green anyway.

Eight pull requests passed a gate that could not fail. I wrote the mask myself, so an unproven step would not block the first merge. That was the wrong trade.

Worse, I cited those checkers as evidence while they were inert. The results I quoted were real, because I ran them by hand locally. The gate was decoration.

On its first genuinely enforced run it caught a violation I had introduced in the same commit.

2. Attribution did not exist

The whole model rests on being able to say who did what. It could not.

PR#8   merged_by=anthony    <- the operator merged this
PR#9   merged_by=anthony    <- the agent merged this

Agent and operator shared one identity. And the fallback signal was already gone, because squash merging regenerates the co-authorship trailer from the commit author:

46d2002 (branch)  Co-Authored-By: Claude Opus 5
fdc49c2 (squash)  Co-Authored-By: Anthony Lewis

I chose squash. Every squash merge erased the agent from the main branch.

The fix was an account of its own for the agent, and disabling squash at the repository level rather than agreeing not to use it. Nine pull requests predate that split and are permanently ambiguous. That history cannot be reconstructed and is not presented as though it could be.

3. A status code is not evidence

The deployment smoke test asserted HTTP 200 from the site’s apex domain. The apex returned 200, serving a Plesk default page dated 2014 from a hosting account I had forgotten about, because DNS still pointed there.

A liveness check would have reported that as a successful production deploy.

The test now stamps the deploying commit into the built bundle and asserts every bound hostname serves that exact commit. Four lines of shell. It caught the placeholder on the run that mattered.

4. Genesis had no gate at all

A repository was created for a product that did not exist. No brief, no requirement, no spec. It reached production two days later and nothing objected.

Neither checker was at fault. Both validate a repository’s internal coherence, and nothing in canonical state linked a repository to the product it serves.

The operator caught it, not a gate. That distinction matters more than the defect: the other failures here were the system working, and this one was the system being bypassed.

5. A reversal, and a correction to this document

A decision was reversed before any of its code was built, which is the cheapest moment to change your mind. The atom work-atom:deliver-container-image-and-tunnel-deployment was refined in place: new title, new purpose, new acceptance checks. It delivered real work and is now done. Its id still says “container” and “tunnel”. It delivers neither.

When this was first published I called that “the model cannot express a reversal” and blamed the status vocabulary. That was wrong, and the error stays visible here because it is exactly the kind this document exists to catch. There are two gaps, not one.

Identity. An atom still wanted, but refined until its id misleads. No status value fixes that. It needs the id to migrate across the atom file, the index, the work graph, every dependency edge and any verification report naming it, atomically.

Terminal state. An atom that will never be built. The status values are proposed, ready, active, done and blocked, so the only moves are to leave it proposed forever, which is a lie because nothing has declared it next, or mark it done, which is a worse one.

The case that occurred was the first. Adding a cancelled status would not have helped.

The identity gap closed on 12 September, three days after this was published. The persistence primitive gained a migrate-id verb. Building it surfaced something else first, which is the better story: an edge naming an atom that did not exist passed every checker in the repository. Edge resolution had to ship before the migration could be proven atomic, because the gate could not see the surface a partial migration was most likely to break.

The terminal-state gap is still open, and deliberately. No atom in this estate has yet been abandoned outright, and adding vocabulary for a case that has not happened is its own debt.

Where it still falls short

  • The checkers test resolvability, not agreement. Since 12 September an edge naming an atom that does not exist is caught. But where a work graph carries its own copy of a dependency list, nothing compares that copy against the atom’s own, so the two can disagree in silence. I injected exactly that drift after the fix landed and it still passed.
  • Nine pull requests are permanently unattributable. See above.
  • The terminal-state gap has no fix. See above, and that is a deliberate choice rather than an oversight.
  • The evidence is uneven. The lifecycle ledger covers product transitions. Ordinary code changes in a delivery repository are attributable through the forge record and nothing else. Those are different levels of rigour and should not be presented as one.

Provenance

Every mechanism here is running code. The tier predicate, the ledger, the span schema, the evaluation verdicts and the checker codes are quoted from a private twelve-repository estate that has run under them since June 2026. The estate spans a regulated gambling product under UK Gambling Commission technical standards, a delivery orchestrator, a governance engine and a cross-language engineering standards corpus.

This site is the first thing built through that model in public. Thirteen gated pull requests, nineteen design tests, and a published record of every change that made it.

The five failures above were found in eight days. That rate is not a boast. It is the argument: a model only earns trust by being run against real work and reporting what broke.