ServicesniikoProcessChangelog
Get niiko

engineering notes

Eleven CI gates, and each one declares what it cannot see

2026-09-02 · Vorluno

A CI check that passes tells you something narrow: that a specific property held, in a specific place, at a specific moment. Teams routinely read it as something much broader — "the thing is fine" — and that gap is where the expensive bugs live. We hit it directly: a gate confirmed a CSS custom property was declared in a stylesheet in the repo, and the compiler dropped the rule on its way to the browser. The gate was green and correct. The screen was broken.

The response was not to add more gates. It was to make every gate state its own blind spot in the first lines of its file: whether it verifies the *source* or the *artifact*, and — when those differ — what could undo the guarantee in between. The CSS gate now says it checks the repo while the guarantee lives in the served stylesheet, and names the CSS compiler as the thing that can deshacer it. The SQL-cast gate says source and artifact coincide, and why: it looks for a shape of code that no bundler rewrites. The theme-pin gate compares two blocks of a stylesheet as they sit in the repo, and says so.

There are eleven of these today, and the list is more interesting than any one of them: unsafe SQL casts, PII handling, PII handlers, migration ordering, CSS variables, theme pinning, dialogs, transitions, Argentine voseo in generated text, plus the responsive gate. Several exist because of a specific incident. The transitions gate exists because a `startTransition` wrapping an async server action without a `try` leaves the screen silent and frozen when the action throws — so no component may call React's `useTransition` directly; they use a wrapper that cannot forget the `try`. The voseo gate exists because our Spanish must never drift into Argentine second person, in the UI or in anything an AI writes for a client.

And then there is the gate that checks the gates: a script that verifies each gate actually declares its source-versus-artifact stance. Without it, the discipline decays in the most predictable way — the next gate someone writes will not have the header, because nothing asked for it, and a convention that depends on memory is not a convention. It is the same argument as the gates themselves, applied one level up.

The broader lesson is about where a lesson should live. We had written this one down in a document first, and it did nothing, because a document is a place you have to decide to go. The message now lives in the error output of the gates that enforce it: when one fails, it explains the trap it is protecting you from, not just which line broke the rule. A document waits to be read. An error finds you.

← All notes

A software studio in Panamá, shipping in English worldwide. The team behind niiko.

Product

  • niiko
  • Modules, in depth
  • Changelog
  • Roadmap

Modules

  • Miira
  • CRM
  • Ciita
  • Kiipu
  • Fiilz
  • Riinda
  • Niima
  • Inbox
  • Notes

Developers

  • Engineering notes
  • Documentation
  • Status soon

Company

  • Services
  • Embedded team
  • Process
  • About
  • For investors
  • Tools
  • Contact
© 2026 Vorluno · Panamá · Privacy · Terms// shipped, not staged.