djrmun.com

Uses

What I reach for, and why. Not a gear list.

Backend

Kotlin and Spring Boot for anything that has to stay up. Postgres for storage until something demonstrably needs otherwise — most reaches for a specialist datastore are premature, and a second system has to earn its operational cost before it earns its place.

Tooling

zsh, and no dependencies. plimsoll is a few thousand lines of shell with nothing to install beyond itself. That is a deliberate constraint for a tool whose whole job is to run on a machine that is already in trouble: a diagnostic that needs a working package manager, a Python environment or free disk space to install into is a diagnostic that fails exactly when you need it.

Distribution via a Homebrew tap, and yes, the install instructions tell you to read the formula before trusting it. A formula is arbitrary Ruby that runs on your machine.

Frontend

Flutter when it needs to be an app, plain HTML when it doesn’t. This site ships zero JavaScript — not asceticism, just that nothing on it needs any, and a page with no script tags has no script-shaped vulnerabilities.

Building with agents

Most of my work goes through an agent now, and the thing that changed isn’t the typing. It’s where the bottleneck sits. Producing plausible code got cheap; deciding whether it’s right did not. So the effort moves to the specification and to the check.

A spec is only worth writing if it’s checkable. If you can’t tell, by reading it, whether a given output satisfies it, it isn’t a specification — it’s a wish with formatting. “Handle errors gracefully” is a wish. “On a 5xx from upstream, retry twice with backoff, then surface the original status” is a spec, because something can be held to it.

The spec is the artifact worth keeping. Code is output, and output gets regenerated. What belongs in version control and argued over in review is the statement of what the thing must do. It’s the same reason the configuration in this project is commented with why rather than what: an agent and a future reader need the same context, and neither arrives with it.

Don’t let the thing that wrote the code write the only check on it. That’s the fourth monitoring mistake below wearing different clothes. A test generated from an implementation is derived from the artifact of success — it passes because the code does what the code does. The check has to come from the spec, or from someone who read the spec, or it’s measuring nothing at all.

Skills and hooks beat repeating yourself. Anything I catch myself telling an agent twice becomes a written constraint it loads every time. Cheaper than remembering, and reviewable — which a habit isn’t.

Where it falls over, in my experience so far: specs that describe implementation instead of outcome, which over-constrain and give back the benefit; specs written afterwards to describe what got built, which are documentation wearing a contract’s clothes; and the one I can’t automate away — output that is fluent, confident and subtly wrong. That last one is the same shape as every other failure I write about here. It returns 200.

Rules for writing a check

All four of these are things I got wrong first. The long version is a post-mortem of a monitor I wrote that could only ever report success. They apply about as well to reviewing what an agent hands you.

Defaults I argue for elsewhere