Writing

All posts

The List That Broke Five Harnesses

Every Kubernetes anti-pattern checker in a five-check harness assumed `---`-separated documents. Naming more than one resource in a single `kubectl get -o yaml` call wraps the result in `kind: List` instead — and every checker silently found zero resources to flag, which looked identical to a clean pass.

Two Tools, the Same Missing Root

Argo CD's App-of-Apps proof lives entirely on the parent; Flux's dependsOn proof is declared by the child and unverifiable alone. Audit either tree without including its root, and both fail the same way — for what turns out to be the same underlying reason.

A Benchmark That Can Never Hit 100

A scoring harness covers nineteen categories of Kubernetes deployment mistake. One of them — drift — can only exist after a manifest has already been applied, which an authoring benchmark structurally cannot produce or avoid. The honest fix was a permanent, documented ceiling, not a future version.

A Tied Score, Two Different Kinds of Wrong

Two models scored an identical 9/9 on a Kubernetes manifest-authoring task, independently reproduced. Reading what each one actually wrote found a self-defeating NetworkPolicy in one and a promotion pipeline referencing a resource that doesn't exist in the other — two unrelated defects invisible to a tied harness score.

The Defaults Nobody Declared

A drift checker pointed at a cluster that had just been applied cleanly reported drift everywhere. The cluster wasn't lying — the API server's own admission defaulting had filled in fields Git never mentioned, and a naive full-object comparison had no way to tell the difference.

The Factory Knows Where to Put It

Two codebases generate an Aggregate's ID in two different places — one in the constructor, one via a Factory asking Infrastructure for it. Eric Evans' own book has a specific, citable answer for which pattern it actually describes, and it isn't the one either codebase's convention assumes.

A Rule Evans Never Wrote

Nearly every DDD codebase forbids referencing another Aggregate by direct object reference — ID only. Eric Evans' 2003 book explicitly permits it. The person who actually wrote the ID-only rule, Vaughn Vernon, says so himself, in the same paper that argues for the stricter rule anyway.

The Same Instant, Two Different Timestamps

The same moment, serialized by the same driver, produces a different string depending on the process's timezone. Four languages had this bug at the call site and one had it at the process boundary — and the fix belonged in a genuinely different place in each, verified by literally running the tests nine time zones apart.

The Automation That Was Waiting on Itself

Every PR a Dependabot auto-merge workflow had ever merged did so by winning a race against its own six-hour deadlock — one of its steps was waiting for a check run that could only finish after that step did. Fixing it surfaced a second bug waiting right behind the first, and a class of half-merge left behind by plain GitHub 502s.

The Image Nothing Noticed Couldn't Build

A Spring Boot 4 migration that checked git history instead of a stale doc, found a workaround for a library a search index insisted did not exist, and ended a day later with the deployable image unable to build — because nothing in CI was watching the file whose meaning had just changed.

Zero Findings, Eighty Bugs

A path-existence checker reported zero findings before and after a three-language audit round that fixed roughly eighty real issues — stale code quotes, an evaluator that grades itself a perfect score for scanning nothing, and a generator still emitting a bug already fixed in the code it was modeled on.

An End-to-End Test That Wasn't

NestJS's e2e suite assembled its own approximation of the app instead of booting the real one, and every language's LLM features had only ever run through their own fallback path. Fixing both surfaced a stranger bug: nock and testcontainers fighting over the same patched module.

A Perfect Score, A Broken Feature

Same doc, same task, two models, run at the same time in separate worktrees. Both self-reported a perfect harness score. Only one of them, independently reproduced against real Postgres and LocalStack, actually worked.

The Bug Came Back, Wearing Five Different Masks

A week after a benchmark task exposed two languages that could not support a second event subscriber, four real features made every language need one. This time all five broke — from a loud boot-time crash to a silent single-handler drop nothing ever logged.

Not Every Report Needs a Server

A monthly statement and a GDPR-style data export both died to the same question: couldn't the client just build this itself? The spending-analysis ETL that survived it, and the rule it revealed.

The Fraud Signal That Trusted the Fraudster

RefundReasonClassifier's fraud-risk score was computed entirely from text the refund requester controlled. Removing it, the sibling ML scorer that went with it, and the one rule the removal left behind.

Narrow What, Never Who

A structured-data RAG feature over an account's own transaction history, the guardrail that lets an LLM touch it safely, and how the same invariant survived five different languages' own conventions.

The Bugs Unit Tests Can't See

A missing @Transactional, a JDK HTTP client retry quirk, a VARCHAR(36) overflow, an SQS FIFO dedup collision — four real bugs that needed real infrastructure to even exist.

Wiring an LLM Into a Domain Service

RefundReasonClassifier reads a refund reason and hands back a signal — the Domain Service that actually decides never calls it, and swapping the LLM backend from Claude to self-hosted Ollama touched almost no test.

A Second Fraud Signal: Scoring History, Not Reading It

RefundFraudRiskScorer is a hand-rolled logistic regression trained on refund history, swappable between a native and an HTTP implementation, feeding the same Domain Service a second independent threshold.

Five Bugs Nobody Was Looking For

Completing incomplete Swagger docs across five languages, verified by actually booting each app instead of trusting the annotations compiled. What it found had nothing to do with documentation — including a Spring Boot 4 dependency split that left production migrations silently never running.

The Naming Rule That Caught Real Bugs

How a boring find/save/delete naming convention, once automated, immediately found violations nobody had noticed across four different codebases.

Same Architecture, Five Languages

Comparing the same Repository/Query split as implemented independently in TypeScript, Go, Python, Java, and Kotlin.

Two Accounts, One Transaction, Five Different Answers

A transfer feature needs one thing every implementation already claimed to support: writing two Aggregates atomically. Building it for real found a working mechanism in one language, a regression waiting one edit inside the obvious fix in another, and a doc that had been quietly wrong about its own code in a third.

The Bug That Needed Two Subscribers to Exist

Five languages scoring 100% on an easy synthetic task taught nothing about where they would fail. A four-level difficulty ladder built specifically to exercise unexercised code paths found the ceiling — and its last rung exposed a fan-out bug that had been invisible since nothing had ever subscribed two things to the same event before.

The Doc Said "Done." Half of It Wasn't.

A repository-naming fix that only reached the write-side interface, four rounds of turning that gap into permanent harness rules, and a yield curve — three or four real bugs per round, then two, then zero — that was itself the most useful result.

How to Find Domain Boundaries

A record of the thought process for organizing complex requirements into Aggregates and Bounded Contexts.

A Path-Existence Checker Found a Real Bug on Day One

No parsing, no understanding of what a code snippet does — just comparing backtick-quoted paths against the real file tree. The exclusion rules that kept it from crying wolf mattered more than the two-pattern check itself, and it still caught a real bug in four docs on its first run.

The Harness Had Never Met a Second Domain

Two harness rules had checked out clean for months — because every domain that ever fed them was Account or Card. Building a genuinely unrelated third domain surfaced two false positives, and confirmed the rule meant to catch a real mistake still did.

Signing In Without a Password

A security audit found /auth/sign-in accepted a userId and nothing else — how the same bug showed up in five languages, and the JDK retry bug a new 401 test uncovered along the way.

When the Docs and the Code Agree to Be Wrong

Three violations across five languages — a Query reading a write Repository, a domain class carrying JPA, a notification module in the wrong layer. Only one was actually a bug, and the other two reveal why dozens of prior audits never caught any of it.

Talking Across Bounded Contexts

Choosing between a synchronous Adapter and an asynchronous Integration Event, with a real compensating-transaction example.