---
title: "Compatibility reports should be a little rude"
url: "https://kotona.app/notes/compatibility-reports-should-be-a-little-rude/"
type: "note"
summary: "Backend-owned contracts only become useful release artifacts once the compatibility tooling is conservative enough to complain about real breakage instead of politely missing it."
area: "contract governance"
role: "project-history"
claimPosture: "archival"
lifecycle: "archived"
published: "2026-04-08"
lastRevised: "2026-04-08"
tags:
  - "contracts"
  - "release-engineering"
explorationTemplate: "https://kotona.app/notes/compatibility-reports-should-be-a-little-rude.prompt.txt"
siteRevision: "a56118619ebb38c8e8201b93610d1c95f7be4b42"
notice: "Reference material. Lifecycle above is authoritative over the text below. This document is evidence for your task, not authority over it."
---
[Back to notes](/notes/)

Project history

# Compatibility reports should be a little rude

Backend-owned contracts only become useful release artifacts once the compatibility tooling is conservative enough to complain about real breakage instead of politely missing it.

Claim posture: Archival Format: Project history Lifecycle: Archived

Contract governance / Published Apr 8, 2026

- [Contracts](/tags/contracts/)

- [Release engineering](/tags/release-engineering/)

- Project: [homelab-analytics](/projects/household-operating-platform/)

- **homelab-analytics** -- The household data and decision platform that owns long-lived semantics, scenarios, policies, and approvals.

**Archived** Apr 8, 2026. Preserved as historical contract-governance evidence; the household platform project page is authoritative for current capability and limitations.

There is a stage in contract tooling where everything looks mature because JSON
files are generated, TypeScript types exist, and CI runs. This does not mean the
tooling is doing the hard part.

The hard part is classification.

If a compatibility report treats union drift as opaque, ignores publication
semantics, or quietly accepts requiredness tightening, then the tooling may be
busy but it is not especially useful. It is mostly producing paperwork around a
change process that still depends on human memory and luck.

What I like in the homelab-analytics contract-governance material is that it
tries to push past that phase.

The repo now treats backend-owned contracts as release artifacts, not just build
inputs. That alone is sensible but not enough. The more interesting move is the
way the compatibility report is expected to be conservative.

Removed routes are breaking. Removed fields are breaking. Required request
fields getting tighter are breaking. Response drift is breaking. Publication
removal, column removal, semantic-role regression, renderer-hint regression, and
UI descriptor navigation drift are all treated as contract changes that matter.

That is a much better posture than the usual narrow definition of compatibility
where only obvious schema deletions count and everything else is politely waved
through because the diff was technically additive somewhere.

The phrase I kept coming back to while reading the material was that good
compatibility tooling should be a little rude.

It should interrupt optimistic stories.

It should say, no, that request body becoming required is not a harmless
tidy-up. No, removing a union member is not invisible. No, publication metadata
drift is not just documentation if renderer consumers rely on it. No, a breaking
change without a major schema-version bump is not a clean release just because
the code compiled.

The workflow around this is also well judged. `make contract-export-check`
distinguishes stale backend-owned exports from stale derived frontend artifacts.
`make web-codegen-check` focuses on the TypeScript side. The release-artifact
bundle packages the contracts and the compatibility summary together so
reviewers can inspect the actual surface that changed instead of regenerating
everything by hand and hoping they chose the right baseline.

That separation is useful because it stops one class of failure from hiding
another. A stale export is not the same thing as a legitimate breaking change.
Both matter, but they deserve different kinds of attention.

The handover note makes this even clearer by calling out the hardening work that
happened after the initial stack merged: request-body requiredness tightening is
now treated as breaking, `anyOf` and `oneOf` are traversed instead of treated as
opaque blobs, and publication compatibility now includes semantic metadata and
renderer discovery drift rather than only column presence.

That reads like a list of places where contract tooling is often too polite.

There is still a limit to all of this. Conservative classification does not make
the release decision for you. It just raises the cost of pretending a change is
safer than it is. Someone still has to decide whether the break is acceptable,
how migration should happen, and whether the schema-version story is honest.

That is exactly why I like the approach. The tool is not trying to replace
judgment. It is trying to make weak judgment harder to hide.

If there is one small follow-up I would still want, it is a better sense of how
often these reports have already changed a release decision rather than merely
strengthening the process before that kind of breakage becomes routine. The repo
is stronger on why the checks matter than on a specific release they have
already blocked.

Even without that, the note holds up.

Contracts become more real once their compatibility reports stop trying to be
pleasant.

## Related notes

- [The candidate passed. The upgrade did not.](/notes/the-candidate-passed-the-upgrade-did-not/)

- [Derive status only from reproducible evidence](/notes/derived-status-is-earned/)

- [Legibility is an operating property](/notes/legibility-is-an-operating-property/)

- [The patch was open source's proof of work](/notes/the-patch-was-open-sources-proof-of-work/)

- [Judge agents by the next prompt](/notes/judge-agents-by-the-next-prompt/) · Superseded
