Anyone can show that an AI writes code these days. That proves nothing. The interesting question is how — which stages, which checks, and what happens when it goes wrong.

This page is the answer, without illustrations. Below: the actual stages Spoor follows, one real fix from report to production with the real timestamps attached, the habits that keep it checkable, and the number of lines of code that came out. Everything on this page was pulled out of our own systems.

The pipeline

There is no human at a button. What sets a task in motion is the combination of three things in Linear: its status, its label, and who it is assigned to. If that combination isn’t right, nothing happens — not later either.

Trigger

Status + label + assignee

A Linear issue in Backlog, assigned to Spoor, without the Refined label. check_backlog.py checks for exactly that every 5 minutes — a plain API call, no language model, no cost. Nothing new means nothing happens. An issue assigned to a human just sits there, however long: nothing times out, nothing claims it anyway.

  1. refine

    Rewrites the issue into an actual brief: problem statement, scope, acceptance criteria. Splits it into sub-issues if it is too big, adds the Refined label, moves it to Todo.

    Safeguard This stage can reach Linear and nothing else — no files, no shell, no git. Deciding scope and touching code are physically separated here.

  2. critique

    A second look at what was just written: is the scope too big, is a criterion missing, do two sub-issues overlap, does a label contradict the text?

    Safeguard Runs as an entirely new process with its own context — not the same session that wrote the text. And it may change nothing: comments only. Having nothing to report is a valid outcome.

  3. resolve_critique

    Actually folds that critique back into the issue: splitting it up, tightening criteria, recording the real dependency, correcting a label.

    Safeguard Rewording a sentence is not enough — the label or the dependency itself has to change, because that is what the later stages actually enforce, not the prose. Disagreeing is allowed, but out loud and with a reason; silently ignoring it is not.

  4. implement

    First claims every actionable issue at once — moved to In Progress, assigned to itself, so a concurrent run cannot pick up the same issue twice. Then works them in parallel, one sub-agent per issue, runs the tests before committing, and opens one pull request per issue.

    Safeguard Each sub-agent works in its own isolated git worktree, never in the copy a human might be sitting in at that moment. And this stage never merges anything itself — that is explicitly the next one's job.

  5. review_pr

    Reads the actual diff, on its own merits. Fixes what is wrong on that same branch, merges (squash), cleans up the branch and moves the issue to Done.

    Safeguard Again a separate process with its own context: not the same session reviewing its own work, and not the summary written by whoever wrote the code. If the diff removes something, the whole repo gets searched for references to the removed thing — by its plain-language name, not just its code identifier.

  6. deploy

    The merge to main kicks off a deploy workflow on a runner on that same VM: only the services the change actually touches get rebuilt and restarted. Then a human gets a message.

    Safeguard A green deploy run is not proof that anything was actually rolled out. Afterwards it gets checked whether that run really did what should have happened — that distinction has bitten us here for real, exactly once.

Steps 1 through 5 are literally the files refine.md, critique.md, resolve_critique.md, implement.md and review_pr.md in this repo. Each one is its own process with its own fresh context — not one long session grading its own homework.

Prefer watching this in motion over reading about it? The Spoor-wiki is an interactive, animated sequence diagram walking through five real cases — this pipeline, who’s allowed to do what, and the hard stop-and-ask list — each step with its own expandable explanation. It’s Dutch-only for now, but the diagram itself is largely self-explanatory even without reading the Dutch.

One real fix, from report to live

On 7 August 2026 someone on the team was testing a new feature: one user does something, someone else’s page updates itself, no refresh needed. It worked — except that they had to refresh. Which was the one thing the feature existed to solve.

  1. Someone on the team reports it over Telegram: the roundtrip works, but he had to manually reload the host's page to see the guest's click.

  2. Acknowledged 25 seconds later, with what happens next. No ticket number, no queue.

  3. Reproduce first, touch code second — against the real production environment, with a real browser session and the real login flow. Result: the server was pushing the update just fine; the host's browser had never subscribed at all. The small script that opens that connection was 404ing, so the page failed silently before anything could listen. A reload looked like it fixed it, but didn't — it just re-fetched the data.

  4. Issue PAI-334 filed in Linear, with the actual root cause written out: one path prefix composed twice over between the reverse proxy and the framework, so the file was looked up in the wrong place. Exactly one route in the entire application was vulnerable to that — this one.

  5. Commit on its own branch, in an isolated working copy. Including a test that pins the bug down: demonstrably red against the old code first, then green against the fix.

  6. Pull request #294 opened: 4 files, +235 / −5 lines, with the reproduction and the verification written into the description.

  7. Squash-merged into main. One commit, one rollback point.

  8. The push kicks off the deploy workflow, on the runner on that same VM. Two seconds after the merge.

  9. Deploy done. 36 seconds. Only the affected service was rebuilt and restarted; everything else kept running untouched.

  10. Tested again in a real browser, now against the live site: guest clicks, the host's page updates itself, no reload. Only then a message back to the person who reported it.

24 minutes and 36 seconds from report to reply, including the reproduction, the test, the review and the deploy.

Two things about that, to keep it honest. This issue didn’t arrive through the pipeline above but over Telegram, and a report from a human is its own scope: the usual planning pass and the independent second look that normally happen before work starts (internally called refine and critique) were skipped here. That’s also why there are minutes between the steps rather than hours.

What wasn’t skipped: reproducing it first and touching code second, a test that pins the bug down before the fix exists, and looking again in a real browser after the deploy to confirm it is actually there. The speed doesn’t come from leaving steps out.

And the cause was, as almost always, unspectacular: the layer that routes incoming traffic to the right place stripped a piece off the address, and the application behind it helpfully glued that back on unasked — so one file got looked up somewhere it wasn’t. Exactly one route in the whole application was vulnerable to that. That one.

How we know it’s right

This is the part that separates “we use AI” from “we let AI write to production unsupervised”. These aren’t promises; they’re rules with a mechanism behind them.

A summary is not proof

“Done, tests green” from the process that just wrote the code doesn’t count as verification here. There is always a separate check afterwards, in a new process with its own context, that reads the actual diff instead of that summary. Not the same session grading its own homework.

Risky work never touches the shared working copy

Every automated task works in its own isolated copy of the code. That’s a rule we learned the hard way: an automated fix once reached into the copy a human was working in at that moment, halfway through combining two sets of changes together, and left the code in a broken in-between state. Since then it isn’t a good intention, it’s a mechanism.

When in doubt, a question comes back — not a guess

There is an explicit list of things Spoor never does on its own, however routine the rest of the task is: a force push, deleting branches, volumes or backups, rotating or revoking credentials, changes to DNS or domains. Those always go to a human first. And silence doesn’t count as approval: where an acceptance criterion explicitly waits for someone’s sign-off, hearing nothing back is not a yes — and neither is merging the change in.

A green deploy is not proof that anything was rolled out

We learned this one the hard way too. There has been a deploy here that finished perfectly green and reported “nothing to do”, while the change that had just been merged hadn’t been rebuilt anywhere. Entirely correct by its own logic — just not a deploy. Since then, after every merge of changes, it gets checked whether that run really did what should have happened, not whether it was green.

Removing something isn’t finished when the code is gone

When a feature or service is switched off, everything the site and its surrounding systems are built from gets searched for references to the removed thing — pages, code, documentation — by its plain-language name, not just the technical identifier it happened to be implemented under. That distinction comes out of a real mistake: the code was gone, the name was still sitting in a handful of documents. The name then goes into a register that gets re-checked automatically every day, with no language model involved. If the term resurfaces anywhere, it becomes a new issue.

So how much code is that?

Lines of code added 44,496

Summed across all 298 merged pull requests in this repo, since 15 July 2026.

7,346 lines removed
985 file changes

Pulled straight from GitHub while this page was being built — not an estimate, not a hand-maintained number. Last build: 07-08-2026.

Lines of code is a crude number — you can prove anything and nothing with it. We put it here anyway, for one reason: it’s real. It gets pulled from GitHub at the moment this page is built, across the whole of Spoor’s own merged work history to date, with no human in between maintaining or rounding it.

What the number does say: this isn’t a test rig that did one impressive thing once. It’s the ordinary working pace of this setup, over a few weeks, including every unavoidable repair of the previous day’s work.

Read on

  • Spoor-wiki — the same chain, as an interactive, animated sequence diagram across five real cases, with an expandable explanation per step. Dutch-only for now.
  • Approach — the same safeguards, written shorter, meant to forward to a colleague.
  • Productivity — the same numbers, broken down further.

Want this inside your own company?

Get in touch →