Field notes / orchestration
Route, don't guess
How the router that decides which AI model gets which task got built, and the near miss that taught it where not to reach.
Every Claude Code session defaults to whatever model it was opened with. Ask it to rename a variable or design a whole subsystem and, left alone, it reaches for the same tier both times. That's fine until the bill notices. The obvious fix is a rule of thumb: cheap model for easy stuff, expensive model for hard stuff. It sounds right. It's wrong, and working out why it's wrong is most of what this project turned out to be.
the routing variableWhat it actually decides
The orchestrator is a routing layer, not another agent framework. It lives as markdown: a contract file, a handful of dispatch templates, an append-only ledger, all read by a session before it delegates anything. No installed dependency, no external scheduler. The bet, made on day one, was that Claude Code's own primitives were already enough, and the missing piece was a policy rather than a platform.
The policy's core move is refusing "hard versus easy" as the routing variable. What matters is task shape: how many correction rounds the work needs, and whether a given round can be checked objectively.
Tests exist or output validates against a schema. → Push down the cost ladder: scripts, local models, then cheap hosted tiers.
Design, debugging, architecture, review. → Stays with the top-tier model, in-session.
Underneath that split sit three costs the "cheap tier for easy tasks" instinct never prices in.
Every delegated session re-derives context from nothing, so handing off a five-minute edit loses outright.
Whoever dispatched the work still pays to read whatever comes back, and a chatty cheap-tier response can erase its own savings.
Cheap models fail more often at anything with judgment in it, and every failure means a redo.
The rule that survives all three isn't "is this task hard". It's whether the expected saving beats the expected cost of doing it again. Iteration-heavy work maximises the wrong side of that inequality no matter how easy it looks.
the pinned tierWhat never gets cheaper
Four categories are pinned to the top tier permanently, however simple the task looks in isolation.
Taste-sensitive output is the first: design, copy, naming, brand voice. A component name is trivial to compute and still wants the model with taste. It turns out "easy" and "low-stakes" are different axes, an idea that arrived from outside the project and earned its place.
The terminal review is the second. Per-task reviews can run on a mid tier, but the whole-branch pass before anything ships always runs top-tier, because it catches what the narrower passes miss. A cheap-tier pass once sailed past a real security hole that a stronger model then caught. The rule dates from that day.
Third, a green light from a cheap tier gates a dispatch but never substitutes for verification. Cheap models have a structural habit of reporting success they haven't earned.
Fourth, the orchestration layer itself. A cheap model was tried as middle manager between the session and a worker. Sixty minutes and roughly fifty tool calls later it had shipped nothing and quietly run a global install nobody asked for. Delegation stays a command the session issues directly. Nobody gets a middle manager.
the evidence ruleProof over promises
Every delegated run ends the same way: a status block in the chat, and a row appended to a ledger file. Neither trusts a bare claim. A "done" needs the tool output, test result, or screenshot sitting next to it.
The ledger isn't decoration. Each row records what was routed where, whether it passed, and the field that matters most: any lesson. A populated lesson is a candidate for promotion into the routing rules themselves. The policy tightens from its own field evidence, not just from design sessions.
the near missThe near miss
The hardest lesson didn't come from a cost overrun. It came from a decision that would have run correctly, in the wrong place.
A "do it everywhere at once" clause, written into one project's own decision log, would have had that project's session run git rm --cached against a sibling project's repository, one it had no business touching. The user caught it before it executed. Nothing was lost.
But it exposed the real default across every project on the machine: any session could offer to edit a neighbouring project's files, and the offer usually looked reasonable.
The fix wasn't a smarter check. It was inverting the default.
A session now treats every other project's tree in three bands:
Reading a sibling's files is always allowed, since no desync is possible.
Writing a note into the sibling's root asking its own next session to decide.
Editing a sibling's facts or running commands in its repo. Two narrow carve-outs: files whose whole purpose is to receive writes, like the routing ledger, and gated edits to genuinely shared config, which always name their blast radius and wait for sign-off.
Everything else routes through a proposal note. It suggests; it never asserts. The receiving project's own next session folds it into its own files, then deletes it. No queue, no index, no daemon. Three ad hoc uses proved the pattern before anyone wrote it down as a rule.
the build logHow it got here
Ten days, roughly a session a day, each one closing with the same four working files (notes, memory, active constraints, rejected approaches) so the next session opens cold and still knows why past decisions landed where they did.
Founded on native primitives
External orchestration frameworks rejected in favour of Claude Code's own agent files, skills, and hooks. First trial ran in a throwaway project on purpose, for zero regression risk while the design was unproven.
The ladder tested for real
A wiki migration ran as the first live trial, with a script, a local model, and two hosted tiers all doing genuine work in one pipeline. The layered-review rule landed that same week, after a cheap pass missed that security hole.
First shipped consumer
A pension calculator's feature became the first real work routed end-to-end through the policy. It surfaced the first known gap: the local tier only speaks Python, and this task was JavaScript. Not a misroute, a disqualification, but a gap worth naming.
Outside validation
An unrelated public routing framework, reviewed independently, converged on the same core shape from a completely different workload. Its one genuinely new idea, taste as a routing axis distinct from difficulty, got folded in. Its "never run high reasoning effort" rule got rejected, since it conflicts with exactly the stages this project keeps expensive on purpose.
Cross-project messaging formalised
Three ad hoc successes generalised into the proposal-note convention.
The near miss, and the contract it produced
Default-deny on cross-project mutation became a standing, machine-wide rule.
Fleet-wide rollout
The enforcement line, the one that makes a project's session actually consult the policy instead of silently defaulting, was offered across roughly eighteen sibling projects. Opt-in per project, tracked from the filesystem alone.
The ledger checks itself
A staleness audit found most adopted projects had quietly stopped logging, so a hook now nudges emission at session end. The same day, a cheap-tier reviewer blamed an unrelated, pre-existing file change on the task it was checking. It got caught by comparing timestamps, and became a standing rule: a cheap tier may scan, but attributing a found change to a cause needs a timestamp check first, not a guess.
what's still openWhat's still open
Two gaps stay visible on purpose. The local tier only routes Python-shaped work, so JavaScript tasks run top-tier by default until a second real JS consumer justifies building a driver. And one mid-tier code-generation route sits in the ladder unproven: named, priced, ready, and untouched, because no task has gone through it yet, and a rung nobody has used is not the same as a rung that works.
Nothing here claims further than what's actually been run. The whole apparatus is a bet that the interesting problem was never "which model is smartest". It was knowing, task by task, when smartest is the wrong thing to be paying for.