Park the stochasticity

Anders Hejlsberg was asked why the TypeScript team didn't just let AI translate their half-million-line compiler into Go. His answer is the clearest statement I know of the idea Colors is built on. Don't ask the model for the translation. Ask it for the translator. Park the stochasticity in a program, and every run after that is deterministic. We made the same trade for infrastructure instead of compilers.

SourceAnders Hejlsberg on why Microsoft didn't rewrite TypeScript using AIyoutube.com/shorts/68qLXn7HUjY

Four quadrants. Flawed, direct AI execution: one agent fans out into stochastic deployment A, B and C, which lead to drift and review fatigue. The solution: the agent writes one deterministic program, the Skill translator, whose every execution is a consistent deployment. Phase one, authoring, agentic once: the agent writes the Package Skill translator, checked by golden tests, multi-language parity and SHA pins. Phase two, operating, deterministic repeatability: colors.yml feeds the execution ladder of ./green build, ./green create --dry-run and ./green create.
the stochasticity is spent either way. the only choice is where it lands

Half a million lines you would have to read twice

When Microsoft announced the Go port of the TypeScript compiler, everyone asked the obvious question. Why not have AI do the rewrite? Hejlsberg's answer has two halves. The first is about what verification costs. Letting a model loose on half a million lines would not, in his words, "absolve us from then having to go in and carefully examine every line that came out of it." Short of perfect test coverage, one-shot AI output converts writing effort into reviewing effort at roughly one to one. The lines still get read, just by a more expensive process.

The second half is his fix, and it is worth quoting at length. "A better approach would be enlist AI to write a program that helps you translate from TypeScript to Go. Because at that point, you can park the stochasticness in that program, and then you can get deterministic behavior whenever you run the program, which means you get the same transformation every time you run it." A model cannot be trusted to do the same thing twice. A program cannot do anything else.

The principle underneath generalizes well past compilers. Nondeterminism is affordable when you author and poisonous when you operate. Anything you intend to run twice should be a program the model helped write, not a model output you sample again.

Infrastructure is run twice by definition

Now move the argument to operations. "Deploy me an Airflow server" is something a capable agent will happily do end to end, and that is the one-shot translation. Every deployment is a fresh sample from the model. The re-deploy after an incident, the second environment, the version upgrade, the migration to another provider. Each one is a new stochastic run. Each one needs the line-by-line check Hejlsberg wanted to avoid, except here the lines are firewall rules, DNS records, and database configuration on a machine that faces the internet.

Infrastructure is the worst possible place to accept that deal, because infrastructure is the thing you run again by definition. Converge, recover, rebuild, scale. The whole discipline is repetition. If the repetition samples a model, you do not have a deployment. You have a distribution of deployments, and you have met exactly one of them.

The translator we ask the agent to write

Colors is what falls out of applying Hejlsberg's move to this domain. The agent's job is not to deploy anything. Its job is to write a Package Skill, a program that translates desired state into a running system. The desired state is a colors.yml. It is flat, kebab-case, and non-secret by rule, so the whole input to the translator is a file you can read in one sitting and diff in one glance.

profile: airflow-digitalocean

provider-compute: digitalocean
provider-dns: cloudflare
compute-prevent-destroy: true

airflow-host: airflow.example.com
airflow-image: apache/airflow:3.1.3
digitalocean-region: fra1
digitalocean-size: s-2vcpu-8gb-amd

The program that consumes it exposes a ladder of verbs, ordered by how much reality they touch:

./green build              # render everything from desired state, no credentials
./green create --dry-run   # walk the whole DAG, skip every side effect
./green create             # converge for real

build is a pure render. The same colors.yml produces the same generated tree, byte for byte, on a fresh checkout with an empty environment. --dry-run rehearses the full execution graph with every side effect skipped. By the time create talks to a cloud API, the transformation it is about to perform has already been inspected twice, and the model was not involved in any of the three steps. The stochasticity was spent once, at authoring time, on the generator. At operate time there is nothing left to sample.

Audit the program, not each run

The payoff of Hejlsberg's argument is that verification concentrates. You review the translator once, with machinery built for exactly that, and every later run inherits the review for free. Colors leans on three such nets.

Golden tests pin the rendered trees. Every package commits the exact output its templates produce for a fixture, and bb golden fails on any drift. After a dependency bump you read a diff of what changed in the render. You do not re-derive trust in the whole output.

Parity makes determinism a cross-implementation property. The SDK exists in three independent implementations, one in Clojure, one in TypeScript, one in Python. The parity suite feeds one fixture through all three and diffs the generated trees byte for byte. Three separately written programs agreeing on every byte is a strong claim that the specification lives in the transformation rather than in any one codebase.

SHA pins extend the same guarantee through time. A deployment's launcher resolves its library at an exact git SHA, so two converges months apart run the identical translator. Nothing in the chain says "whatever the latest version does today". An unpinned dependency would let the transformation drift while every input stayed the same, which is stochasticity sneaking back in through the side door.

Writing the translator is itself a procedure

One stochastic step remains. Someone has to sit through the authoring session in which an agent writes a new Package Skill. We do not pretend that step is deterministic. We fence it. The Create Package Skill workflow that drives it is a three-phase state machine. Phase one is conversation only. Scope, naming, and an explicit list of what the agent may do, including creating repositories, spending money, and touching DNS, all settled before a single file exists. Phase two scaffolds the desired state and the credential conventions, with secrets confined to a gitignored file the agent never reads. Phase three is autonomous execution against a definition of done that reads, line by line, as a checklist of deterministic properties: generated files reproducible, golden checks passing, builds and dry runs working from a fresh checkout without credentials, pins pointing at real pushed SHAs.

The agent's judgment is confined to the one place it pays, and its output does not count as done until the deterministic nets accept it. That is Hejlsberg's argument applied twice over. The first move parks the stochasticity of operating in a program. The workflow parks as much of the stochasticity of authoring as a procedure can hold.

The same KPI, stated from the compiler world

Regular readers will recognize the shape. Agentic Once, Deterministic Forever framed safety as a ratio, deterministic tasks over agentic ones. The compounding-advantage article framed progress as agentic work converting into an executable corpus that never converts back. Hejlsberg's answer is the same claim arriving from a different field, made by someone with no stake in ours. When the work will be run more than once, the valuable AI output is a verified program. The expensive AI output is a pile of one-shot results you must re-check on every use.

The TypeScript team reached that conclusion looking at one compiler. I think it holds for every server you will ever have to rebuild at three in the morning. Hand your agent the Create Package Skill workflow, or start from a Package Skill someone already verified. Either way, let the model write the program, not the deployment.