In production
An agentic SDLC
A written contract, six rules each earned by something breaking, and guardrails asserted by CI rather than documented. Two agent runtimes, one source of truth.
Most advice about coding agents is about prompting. The harder problem is everything around the prompt: what the agent is allowed to do, what it must write down, and who checks that it did.
So the instructions are a contract. One file at the repository root, with the tool-specific entry point a symlink to it, because a rule that exists for one tool disappears when you change tools. Both runtimes read the same bytes.
Six rules, each earned
The rules are tool-neutral and carried between projects. Every one exists because something broke:
- Never copy live system output into committed source. Log lines and API responses carry credentials, signed URLs and personal data. Fixtures are synthesised; assertions are on structure, not values.
- A predicate over machine-generated text is validated against a real captured sample before it ships — regexes over error messages included.
- Time-windowed queries describe a window, never the present. Before reporting something is currently broken, confirm it against durable state and say which source you used.
- A local tool result is evidence only if the local version matches the version that gates the change.
- Never advance past a work item until its durable record is confirmed written. Acknowledging with nothing recorded destroys the only evidence the work existed.
- When the pipeline is metered, batch work into one push.
Rules 3 and 5 are the ones people are surprised by, and they are the two that cost the most to learn.
An autonomy ladder that is dated
Autonomy is policy, not a setting, and it is granted explicitly:
- L0 — branch, edit, test, commit, run the local gate. Always.
- L1 — push an agent branch so a pipeline validates it. Enabled on a specific date, after the rails were proven.
- L2 — scheduled or headless runs. Explicitly not enabled.
The interesting entry is the last one. A capability deliberately withheld, with the reason written down, is worth more than one switched on by default — and recording when L1 was granted means the decision can be revisited against what was true at the time.
Guardrails that can fail
Documentation drifts; assertions do not. The contract is checked by a script that runs in CI, and the script has a selftest that mutates the repository to prove each check can actually fail. A check nobody has seen fail is a check nobody should trust.
That is also how the knowledge base stays honest. Every lesson is one always-loaded index line plus one lazily-loaded entry, and the two are asserted in parity in both directions — the full write-up is here. Eighty entries, each earned by a production break or a near-miss — 5.3 KB of always-loaded routing against an 11.5:1 lazy ratio, so the knowledge base grows without the sessions paying for all of it.
What it is not
Nothing runs unattended. There is no autonomous pipeline, no agent merging its own work, no unreviewed change reaching production. The value is not that the agent is trusted; it is that the boundaries are written down, machine-checked, and widened one dated decision at a time.
I prototyped all of it on my own projects before it went anywhere near work, and adopted it there only once it had earned its place.