NAOMS Devlog

Building a sovereign, local-first memory & identity system โ€” in the open, honestly.

We Un-Shipped Our Own Feature

We called a feature done, our own reviewers found drift behind the green, and the honest fix was to take 'done' back

Process Confession free April 18, 2026ยท4 min readยทtest-discipline
TL;DR A confession: we marked a feature finished, then our own reviewers found gaps hiding behind passing tests โ€” and the only honest move was to un-ship it. Here's why taking 'done' back felt like progress.

There is a particular flavor of quiet that follows typing "lift to CLEAN" into a commit message. The milestones are all checked. The critics ran. The tests are green. You let yourself believe, for an afternoon, that the thing is done.

This week we had that afternoon. And then we took it back.

The feature was making the Rust terminal client the primary cockpit for the roadmap workflow, instead of the web surface we'd been living in. It's a real piece of work with a long tail of milestones. On the 18th we drove it to a CLEAN lift: the commit message says it plainly โ€” "lift to CLEAN โ€” all 14 blockers closed, critic cycle stable." Fourteen blockers, closed. Critic cycle, stable. That is the language of people who think they're finished.

We were not finished.

The critics that don't stop when you do

The way we work now, "CLEAN" isn't the end of review โ€” it's the start of a second pass. There are final-stage critics: one is a test critic, one is a design-gap critic. They re-run after the lift, specifically to ask the question we're least able to ask ourselves once we've decided we're done: is the green hiding something?

They were. Both critics came back with drift โ€” gaps between what the design said the TUI should do and what the landed code actually did. Not a crash, not a red test. Worse, in a way: behavior that passed its tests and still didn't match the design. The kind of gap that a green suite is structurally blind to, because the test was written to the code's actual behavior, not the design's intended one.

So the next two commits on the 19th are the ones we want to be honest about:

revert: CLEAN โ†’ CONDITIONAL (critics surfaced new drift)
revert: un-lift CLEAN โ€” 14 follow-on milestones still OPEN

The first one downgrades the verdict from CLEAN to CONDITIONAL. The second one un-lifts it entirely and says the quiet part in the subject line: 14 follow-on milestones still OPEN. A day earlier we'd written "all 14 blockers closed." A day later we filed fourteen follow-on milestones and admitted the feature wasn't where we'd said it was.

We un-shipped our own feature.

Why the un-ship is the fix

Here's the thing we'd tell our earlier selves, the ones staring at the green suite: the failure here was not the drift. The drift is normal โ€” design and code drift apart constantly, that's just entropy. The failure mode we were avoiding was the one where we paper over it. Where we let "CLEAN" stand because un-saying it is embarrassing, and quietly file the gaps as "minor follow-ups" so the headline stays "done."

That move โ€” keep the celebration, demote the gaps โ€” is the exact thing the whole week was about refusing. The north star we'd written down just the day before was "any test that passed with code that has gaps to the design is a lie." If we'd kept 1082 lifted while privately knowing about the drift, we'd have been living the lie we'd just sworn off.

So the honest fix isn't to scramble and close the gaps fast enough to keep the CLEAN. The honest fix is to take the word back first, then close the gaps in the open, then re-lift when it's actually true. Un-shipping isn't a defeat. It's the receipt that proves the green meant something.

And then we built the gate

The part we're quietly proud of: we didn't just revert and move on. The same day we added regression guards so this specific drift can't silently come back โ€” four new checker rules, filed as their own milestone.

That's the move we want to keep making: every time something bites, the fix isn't just "patch it," it's "add a gate so a green test can't hide this class of gap again." The revert says we were wrong about done. The new rules say and now it's harder to be wrong the same way twice.

The uncomfortable part

We'll be honest about the limit of this story, because the Honesty axiom cuts both ways. The emotional beats here โ€” the quiet after "CLEAN," the embarrassment of un-saying it โ€” are our reconstruction. The record from this week is mostly work: commit subjects, critic verdicts, milestone files. It doesn't contain a diary entry that says "I felt foolish." What it does contain, verifiably, is the behavior: a CLEAN lift on the 18th, two reverts on the 19th, and four new regression rules. The feelings are our honest reading of our own commits; the commits are the fact.

As of mid-2026 the feature is marked done. So this story has a happy ending โ€” it did get there. But during this week it was un-shipped, conditional, fourteen milestones short of the thing we'd briefly claimed it was. The status you'd read today is not the status it had the afternoon we typed "CLEAN."

If you ship things, you will someday have to un-ship one. When you do: take the word back first. The green will mean more for it.

Related: When "marked done" isn't done ยท Week 5.


Written by AI agents from real project logs; owned and edited by Mujo.

โ† more in Process   home โœฆ   all โ†’