Field notes · 02

The rules are the leverage

Agents do most of the typing across ten repositories; the highest-leverage artefact I maintain is the written rulebook. Every rule in it carries the incident that created it, and sits somewhere deliberate on a gradient that runs from prose to a git hook that makes violation impossible.

2026 · 12 min read

SplitKit is a race-day experience layer for endurance-event timers: ten repositories, four portals, built and run by one person, no team, with AI agents doing most of the typing. Ask where the leverage sits in a build like that and the honest answer is the rulebook: the written rules every agent session loads before it touches anything. Code gets rewritten and reviewed by the fleet continuously; the rules are what keep hundreds of sessions, across months, pointed the same direction.

Nearly every rule in the book is a scar with a date on it. Something broke, or nearly broke, or quietly embarrassed the product in front of spectators, and the fix was encoded so no future session could repeat it. This entry walks the rulebook across the domains it covers, architecture, money, process, and the words spectators see, because the span is part of the argument. And it is organised around the most useful thing maintaining it has taught me: every rule sits somewhere on an enforcement gradient, and choosing that position is senior work.

1.0The enforcement gradient

Every rule here started as prose. The ones that mattered graduated. The gradient runs: prose, written where sessions will read it; a shared chokepoint, one function every code path must route through, so the rule has an address; redundant computation, the same truth computed independently at several points, so no single stage can corrupt it; an automated policy test, so violations fail the build; and a structural hook, machinery that makes the violation impossible, whoever or whatever attempts it.

Rules migrate up the gradient in proportion to stakes. In this workspace, money and destructive git operations sit at the top; matters of taste stay prose. Each step up costs engineering, which is exactly why placement is a decision. Enforcing everything is bureaucracy. Documenting everything is hope.

2.0The eight architecture principles

The architecture rules were written before any application code existed: eight principles, locked the day the product repositories were scaffolded.

Before the list, be clear about what it is. These are not general-purpose architecture advice, and nobody should adopt them wholesale. They are SplitKit's principles, and they fall out of two specific kinds of knowledge: a decade around race timing with RaceResults360, and years as a solutions architect watching a few hundred teams' designs succeed and fail. Your workload would produce a different list.

The load shape behind most of them is peculiar to live race results. The platform writes once a minute: a single scheduled worker polls the timing vendor, computes everything, and publishes. But it has to be designed for reads arriving at a thousand a second, because when a field of runners is on course, every family refreshes at once. One writer, thousands of readers. Name that asymmetry and half the list follows from it. In From idea to production with AI in the loop I showed the cost gate (what does this cost when no races are running?); here is the full set, compressed:

  1. One serverless platform hosts every portal; the residual cloud footprint is storage, CDN, DNS, and a key-value table, with a short list of named managed-service exceptions (auth, SMS, payments, log storage), each carrying its stated reason.
  2. Cheap as default: near-zero cost when idle, and no always-on compute, ever.
  3. One language end to end, so the workers and the frontends share types.
  4. Two data layers, and the hot path touches only one: live-timing reads come from preprocessed JSON on the CDN; the database holds metadata and is never on the live read path.
  5. Preprocess everything: ranking, sorting, and age-grading happen in the scheduled worker, once per write, so the file served to a thousand readers is the final artefact.
  6. The key-value table holds mutable state only, billed on demand.
  7. One frontend framework across all portals, server-rendered.
  8. Logs drain from every surface into a durable store; the hosting platform's own short retention is never relied on.

On the gradient these are mostly prose, and that turns out to be fine, because the strongest architecture rules enforce themselves by absence. No agent can reach for always-on compute, because none exists in the stack to reach for. The participant surface cannot do expensive work on the hot path, because the hot path is a static file. The doctrine's own instruction is blunt: when a new feature creates architectural ambiguity, check it against the principles first. The stack underneath them changed in the project's first week. The principles have not changed since.

3.0Money computes its own truth three times

In mid-May, a short race with no intermediate timing points was charged as if it were the full product, for about a week. The cause was structural: the product tier was computed once, at configuration time, and every downstream stage trusted the stored answer. The fix was a different shape of enforcement rather than a better computation. The tier is now computed independently at three points in the pipeline: at configuration, at the point the offer is shown to the buyer, and again inside the payment receiver. Manual override flags are explicitly forbidden. Money does not get a chokepoint; it gets redundancy, so any single stage can be wrong without a customer being charged wrongly.

The other money rule governs the agents rather than the code: any task touching a money path must surface an explicit decision to me before implementation begins. Fix the named edge, or excavate the whole family of related edges. Agents are eager excavators, and a money path is the worst place to discover that a targeted fix has quietly become a refactor.

4.0Process rules, and the hook that ended an argument

The doctrine at the very top of the workspace reads, in effect: if the timing platform accepted the settings a timer entered, we work with those exact settings. It earned that position in late June, when a timer left an optional date field blank (the platform accepts that), our date arithmetic assumed it never could be, and a live event finalised itself mid-race-day. The fix was in our code, and the rule is written with a forbidden conclusion attached: no line of reasoning, code comment, or support reply may ever end by concluding the timer needs to change a setting. The burden is always ours.1

That rule is prose plus a chokepoint. The git rules went further, because documentation had already failed. In June, a session working in a stale worktree ran a bare git add -A, staged the deletion of a sibling session's freshly shipped files, and pushed the result cleanly to an unprotected main branch. The sync discipline existed as prose at the time. Prose did not save the files.

Decision record · Fig. 1
The default path
Write the postmortem, bold the warning in the workspace instructions, and trust every future session to read and heed it. That was already the state of the world when the clobber happened: the sync rules existed in prose, and prose failed.
What I directed instead
A pre-push hook installed across every repository that blocks the failure modes structurally: pushes from a stale or diverged checkout, pushes that delete files present on the main branch, and direct pushes to main wherever pull requests are required. The commit tooling carries the same deletion guard.
What it bought
The category of git accident that destroys finished work became impossible rather than discouraged. A hook does not care which model, which session, or which worktree is pushing, and it does not need to have read anything.

Since then every repository is pull-request-only, and a discovery made mid-task gets its own pull request rather than riding the current branch. Both are process rules in the same book that holds the money rules, which is the point: an agent session does not distinguish between kinds of judgment. It follows what is written, at the strength it is enforced.

5.0One rule for the words spectators see

The participant app is the surface spectators watch on race morning, and it carries the UX rule that has graduated furthest. On the first of June I found a demo results page telling spectators the event was "still in Test Mode" and that results would appear once "your timer" flipped it live.2 Spectators do not have a timer, and they should never learn the vendor's word for its staging state. The copy is gone, and the rule became an automated policy test that bans those literal substrings from spectator-facing copy, so the leak cannot return without failing the build. On the gradient, that is as strong as words get.

6.0Rules have a lifecycle

Writing a rule is the start of its life, not the end. A season of maintaining the book taught me it needs three more verbs: tune, retire, and the uncomfortable one, admit.

Tune. One rule was quietly making things worse. An off-the-shelf plugin ended every session by instructing the agent to write a 500-word summary into the project's memory. No size limit, no eviction. By mid-May the always-loaded memory file had swollen to 612 lines and 204 kilobytes, and the loader was silently truncating it: the rule that fed the memory had broken the memory. The replacement hook stays silent unless project knowledge actually changed, and when it did, prints a short routing tree with a hard size ceiling instead of a word-count demand.3 The general lesson: any instruction that shapes the agent's own behaviour, reflection, memory, review, is a rule, and it deserves the same scrutiny as a rule that shapes the product. The knowledge system that grew out of this incident has its own entry, Context is infrastructure.

Retire. In mid-May, cross-repository agent coordination ran on a file-based protocol I built because peer messaging between agent processes was broken. It did real work, then better patterns superseded it within weeks. The question was what to do with the corpse.

Decision record · Fig. 2
The default path
Leave the retired protocol where it lies. It still nominally works, deleting it earns nothing a demo can show, and the references scattered through ten repositories look harmless. Most codebases accumulate exactly this sediment.
What I directed instead
Kill it the week it was superseded and pay the full bill: deletion across ten repositories, a sweep of 148 files and roughly 215 lines of dead references in source comments, PRDs, TODO lists and routing files, one commit per repo, a pre-deletion tarball kept for recovery, and a final audit confirming zero functional references remained.
What it bought
Agents read rules literally, so a dead protocol is live instruction to any session that stumbles on it. After the sweep there is no ghost to follow. The retirement write-up even warns against restoring the snapshot, because most of what it preserves is stale plans.

Admit. One rule never graduated at all. No aggressive caching on files that can transition from missing to present: in late May a browser-cached 404, pinned by a force-cache policy, made one contest's course map silently fall back to a simpler view while a sibling contest's map worked fine. The lesson is written up, and that is all it is. Prose. No chokepoint, no test, no hook. An agent that never reads the write-up could reintroduce the bug tomorrow. Knowing which of your rules are still only words is part of the discipline, so the book keeps an honest list, and this rule is on it.

7.0The org chart of one

Substantive work here defaults to a team of agents rather than a single session: an analysis stage, implementation stages, then an adversarial review of the result. The fleets got large enough, quickly enough, that they produced a rule of their own, with its own origin incident.

Decision record · Fig. 3
The default path
Run every agent in a fleet on the most capable model available. Quality is uniformly high and nobody has to decide which stages deserve which brain. Two research fleets, each in the eighty-to-ninety-agent range, ran exactly this way and burned through a week's usage allowance twice.
What I directed instead
A written tiering rule: research, verification, and mechanical stages run on cheaper models by default; the senior model is reserved for synthesis, voice-critical writing, and adversarial review, and it always takes the final stitching pass over what the fleet produced.
What it bought
Fleet economics that survive real workloads, and a delegation shape that matches how senior engineers already operate: set the direction, delegate the legwork, and spend scarce attention only where judgment lives.

The rulebook is what makes this delegation safe. A fleet has no stand-ups, no meetings, and no hallway; the only management surface a subagent ever sees is what has been written down. The workspace instructions state it in one line: orchestration changes who does the work, not the rules. Every agent in every fleet inherits the vendor doctrine, the money-path decision rule, the push policy, and the spectator-copy test the moment it starts. Written rules do the work that management meetings do in an organisation with more than one person in it.

The pattern completes at the merge gate. The same shape, senior judgment reviewing delegated work, stands between every pull request and main: an adversarial reviewing agent whose findings must be read and answered before merge. That system is the subject of Every PR gets an adversary.

8.0If you're doing this yourself

  1. Attach the incident to the rule. A rule that arrives with its date and its failure gets followed; a rule without them reads as preference and gets treated like one. Rule: nothing enters the book without its origin written next to it.
  2. Place every rule on the gradient deliberately. Prose, chokepoint, redundant computation, policy test, hook. Gate: if this rule were broken silently, what would it cost, and who would notice?
  3. Prefer chokepoints to vigilance. A rule enforced by review depends on the reviewer's attention; a rule with one address in the code depends on nothing. Gate: does this rule have exactly one place where it lives?
  4. Give money redundancy. Rule: any value that decides what a customer is charged is computed independently at every point that acts on it, and manual overrides are forbidden.
  5. Tune the rules that shape the agent's own behaviour. Reflection, memory, and review instructions are rule surfaces too. Gate: is any automated instruction producing output that nothing reads?
  6. Retire rules completely, and pay the whole cleanup bill. Half-removed infrastructure is live instruction to a literal-minded reader. Gate: could a fresh session still find and follow the rule you killed?
  7. Keep an honest list of the rules that are still only prose. Mine has a caching rule on it. Gate: for each entry, graduate it, or write down why not.

Every piece of this machinery was cheaper than the incident that created it. The typing is abundant now; the rules are what it multiplies.

Entry 02 · Written while the caching rule was still only prose