Tooling · Testing

The Harness Had Never
Met a Second Domain

Two rules in the compliance harness had checked out clean for months — but every domain that had ever fed them was Account or Card. Building a third, deliberately unrelated domain and running it through the same harness surfaced two false positives hiding in plain sight, then confirmed the rule that was supposed to catch a real mistake still did.

The question was where to take the repository next — a scaffolding template for new projects, the harness pulled out as a standalone tool, write-ups of what the process had turned up, an AI benchmark. All four were worth doing, and all four assumed the same thing underneath them: that the harness itself was actually checking what it claimed to check, on any domain, not just the two it had ever seen. That assumption had never been tested directly, so it went first.

Grep Said It Was Fine

The obvious first check was searching the harness's own rule implementations for hardcoded account/card strings — and it came back almost clean; the only hits were inside comments giving examples. By that measure, the harness was already domain-agnostic. But "doesn't mention the domain by name" and "works correctly on a domain it's never seen" are different claims, and only one of them can be tested by reading the rule code.

So Build a Domain the Rules Have Never Seen

The repository already documents its own answer to "how do you add a new domain" — docs/reference.md's reference implementation template. Following it literally, in a scratch copy, produced a real Order domain: its own CQRS CommandHandler/QueryHandler pair, its own domain event, and — the detail that mattered — its own dedicated OutboxRelay, unrelated to Account or Card in every way except following the same rules. Then the harness ran against it exactly as it would against real code.

The score moved from 98 to 100, which is a good number in the wrong way to be interesting on its own. What was interesting is that it moved because two rules turned out to be flagging code that was correct.

Two Rules, Two Kinds of Blindness

domain-event-outbox.evaluator.ts collected every domain-event name across the whole application into one set and required each individual *-outbox-relay.ts file to cover the entire set. That's backwards from how the repository actually works — every domain owns a relay that handles only its own events. With one domain in the repository, "the app-wide event set" and "this domain's event set" are the same set, so the rule had never once been wrong. Add a second domain with its own relay, and it starts failing correct code by construction. The rule itself was only a few days old, added in an earlier round when the repository still had exactly one domain to write it against.

The pagination rule had a plainer bug: it regex-scanned an entire repository file for /data|items|result:/ and flagged any hit, anywhere. Order has a legitimate items field — an order's line items, nothing to do with pagination — and the regex couldn't tell the difference. Account and Card simply never happened to have a field with that name, so nothing had ever forced the distinction.

The same shape, underneath

Neither bug is visible from reading either rule in isolation, and neither is a matter of the rule containing wrong logic in any local sense — both only exist once more than one domain is in the picture: a global set that should have been scoped per-domain, and a field name that happened not to collide until something new was built. Grep-auditing for hardcoded domain strings can't find either, because neither rule mentions a domain name anywhere.

Both were filed and fixed the same day, one commit: the event set narrowed to each domain's own directory instead of the whole app, and the generic-key check narrowed to the literal return-type shape a paginated response actually has — Promise<{ items: T[]; count: number }> — instead of scanning the whole file. Four regression fixtures went in alongside the fix — a good and a bad case for the multi-domain scoping, a good and a bad case for the field-name collision.

Checking That the Fix Didn't Also Remove the Detection

Narrowing a rule to stop a false positive is exactly the kind of change that can quietly also stop catching the real thing. The same session had an actual mistake sitting in the repository — three error codes missing from an enum, entirely unrelated to either fix — and the harness's error-handling.error-code.enum-count-mismatch rule caught it both before the narrowing and after. The false positives were gone; the detection wasn't.

What the Exercise Actually Tested

"How many rules only Account and Card have ever exercised" turned out to be the more useful question than "how many rules mention Account or Card by name" — low string-coupling and correct generic behavior are not the same claim, and only one of them survives contact with a second domain. Both bugs shared a precondition neither static reading nor the grep audit could produce on its own: they only exist once more than one domain coexists in the same codebase. The practice that followed from this is mechanical — a new or changed harness rule now gets run once against a domain deliberately unrelated to whatever prompted it, not just against the two the repository already has, before it's trusted to be generic rather than merely untested.

Further reading in the repo

implementations/nestjs/docs/reference.md — the new-domain template the Order build followed exactly · pagination.evaluator.ts — the fixed generic-key check, scoped to the response type literal