# One question, one home: why parity beats correctness

> When a screen and an API answer the same question through separate implementations, one of them will eventually be wrong — and the disagreement is itself a defect, even when one side is correct. A real incident where the dashboard was right, the agent tool was wrong, and the wrong one filed a bug against innocent code.

URL: https://biloh.com.au/docs/engineering-notes/one-question-one-home
Category: Engineering notes | Audience: builder | Updated: 2026-08-28

## The rule

Every question the product can answer should have exactly **one** implementation, called by every surface that asks it.

Not "two implementations that agree today". One.

## The incident

A bug arrived from an agent: *"invoice send delivers to only ONE flagged contact, not all of them."* Severity high. It named a plausible cause — a collapse in the recipient resolver, somewhere an array was being reduced to its first element — and suggested fixing exactly that.

Everything about the report was reasonable. It was also wrong in the way that matters most: **it pointed at working code.**

## What the evidence said

Delivery events are written by the email provider's webhook, independently of anything the application believes it did. Reading them directly for the invoice in question turned up eight rows — `sent` *and* `delivered*, for **both** contacts, on **both** sends, under four distinct provider message ids.

The fan-out had always worked. Nobody had missed an invoice.

## Where the fault actually was

The delivery-status tool resolved a **single** message id from the entity row, then filtered the entire event timeline by it.

That is fine for a send to one person. But the send loop dispatches **one message per recipient**, each with its own id, and stamps the entity row with the *first* one. So the filter kept one recipient's events and discarded every other. Asked about that invoice it returned two of eight rows — both for the same person.

An agent read that output, drew the only available conclusion, and filed a bug against the resolver.

**The instrument produced the alarm.**

## The part worth generalising

The dashboard had been right the whole time.

Its endpoint queried the delivery events by `(entity_type, entity_id)` — the natural key, complete by construction — and had always shown both recipients. Two implementations of one question. One correct, one not.

That is the lesson, and it is not "the API had a bug":

> **A second implementation is a liability even when it is correct.** Correctness is a property of a moment. Parity is a property of a design.

Had both surfaces shared a resolver from the start, the bug could not have existed — not because the shared code would have been better, but because there would have been nothing to diverge *from*.

## The compounding risk with agents

When only humans consumed the API, a disagreement like this produced confusion. With agents in the loop it produces **artefacts**: a filed bug, a suggested fix, and a plausible case for changing correct code.

Following that suggestion would have loosened a de-duplication rule that stops two contacts sharing one mailbox receiving two copies of every invoice. The "fix" would have introduced a real defect to resolve an imaginary one — a strictly worse outcome than doing nothing.

An agent's report is evidence about **what the agent saw**. Confirm what actually happened before acting on what it concluded.

## What shipped

- One resolver, keyed on the entity, called by both the dashboard endpoint and the agent tool. Neither keeps its own query.
- A pure roll-up function — events in, per-recipient summary out, no I/O — so every rule in it is exactly testable.
- A `keyed_by` field on the response, saying whether the answer is complete (`entity`) or partial (`message_id`).
- A per-recipient array, because a flat timeline of eight rows never answered "did both people get it".

## The residual defect, which was real

Re-diagnosis does not always mean "no bug". A bounce is recorded against the **bouncing recipient's** message id — usually not the stamped one. So the old tool reported `delivered` from the first recipient's record while another contact's address was dead.

The summary now takes the **worst** outcome across recipients, evaluated before the entity row's own status flag. A failure on any recipient cannot hide behind someone else's delivery.

That hole was closed before a live bounce found it.

## Checklist

When adding a surface that answers an existing question:

1. Find the existing implementation. Call it.
2. If it does not fit, change it so it does — do not fork it.
3. If you genuinely need a second read path, make the difference **visible in the response** (`keyed_by` is that).
4. Write the shared logic as a pure function. Testability is what keeps two callers honest.

## Related

- [Verify an email actually reached your client](/docs/how-to/verify-an-email-reached-your-client)
