DEV Community

Cover image for The Deploy Was Boring. That Was The Whole Point
Jeel Vankhede
Jeel Vankhede

Posted on • Originally published at jeelvankhede.hashnode.dev

The Deploy Was Boring. That Was The Whole Point

You know the ten minutes before a deployment. The finger near the button. A dashboard open in the next tab. That low hum of waiting for something to go wrong.

I sat through those ten minutes more than I can count now! If you have been following this series then it was for the notification scheduler refactor this time. I had braced for them all week.

Nothing happened.

The change went out. The checks that needed to be green were green. The queue kept scheduling notifications. No alert fired. I stayed on the dashboard longer than I needed to, waiting for the problem I was sure was coming.

There was no problem.

That emptiness bothered me more than a failure would have. A failure I would have known what to do with. A deploy this quiet felt like I had skipped something.

I had not skipped anything. What I did not understand yet was why it was quiet, and what that quiet was actually worth.

Ship does not ask whether it works

By the time I reached the button, the question of whether the code worked was already closed. Test had closed it. The call-order change that Review had scored partial went into Test, came out with a real failure found under one timing condition, went back in fixed, and the evidence was recorded both times.

Ship was not there to answer that question again.

Which meant the tension I felt in those ten minutes was not about this deploy at all.

I have felt it at most deploys I have run. I had always filed it under deploy risk. It was not deploy risk. It was unpaid work from the earlier phases, all coming due at once, in front of production.

A deploy that makes you nervous is a carry forwarded question it should not be in the first place.

This one was not carrying any.

Boring was not luck. Boring was what the earlier phases had already paid for.

The absence of an error is not evidence

There was one requirement I would not let the quiet speak for.

The external notification provider does not fail loudly. Send it a payload with the wrong shape and it does not throw. It accepts the request, drops the content in silence, and the only evidence arrives weeks later, when somebody notices the notifications that never came.

So there I was, taking comfort in a silent dashboard. And silence was the same risk this whole contract had been circling since Plan, since the beginning.

I could not tell the two apart. A clean deploy and a silently rejected payload look identical from where I was sitting.

The absence of an error is not evidence.

"It did not error" and "it worked" are the same sentence to a system that never errors either way.

That requirement was not marked shipped because the deploy went quietly. It was marked shipped because Test had produced evidence behind it before I ever pressed the button. The quiet confirmed nothing. The evidence did.

That is not a technicality. It is the line between a boring deploy and a deploy that looks boring which leaks later.

I wrote the rollback before I shipped, and then I did not need it

Ship would not let me move without a rollback on record: a written trigger, a written action, a named owner. Not a vague sense that I could revert if things went bad.

The trigger was the only part that took real thought, because it could not be "an error appears." This provider does not throw one. A trigger for a silent failure has to be something a person checks on purpose, not something that shows up on its own. Review and Test had already named the risk twice, so I was not hunting for a new one. I just wrote down that I would go looking for it. The action was a single revert of the dispatch change. The owner was me.

Then the change went out, and I never touched any of it.

From the outside, an unused rollback looks like wasted effort. It was not what kept me calm exactly, the dread was still sitting right there, but it gave the dread somewhere to go if it turned out to be right instead of leaving it to circle with nowhere to land.

An undo you never use is not a cost. It is the reason you can stand still and watch.

Shipped is not a feeling

Then the quiet started making its own argument.

Nothing had failed. The checks were green. The queue was scheduling. Every instinct I had was pointing the same direction. This is done. Close the tab. Go do something else.

That is the instinct I no longer trust.

Ship will not record anything it cannot show. A pull request, a CI run, a release, a handoff to whoever is downstream, none of it counts without evidence behind it. And local state never counts on its own. Merged is not shipped. Green is not shipped.

I have said "it is done" about work that was merged and never released. It did not feel like a lie when I said it. That is what makes it dangerous.

Shipped is not a feeling. It is a claim, and a claim needs something standing behind it.

The recommendation came back ship. Not because the deploy felt fine. Because every requirement had a state, every state had evidence, and the one way this could still go wrong had a trigger, an action, and my name on it.

What comes next

Ship closes with an artifact. Not what I intended to ship. What the evidence supports. What actually went out, what was deferred, and what is still waiting on a human.

That last category is the one that matters after the tab closes. A deferred item without an owner is just something the next person finds by accident.

Reflect starts from that record. It does not ask whether the feature works, or whether it went out. Those are settled, and they are written down.

It asks what the process itself cost and what it bought, now that the whole contract has run once, from the first brief to a deploy so quiet I had to talk myself out of walking away from it.

That is the next part.

A key takeaway:

ship.md is the skill running underneath all of this. It is what actually decided ship, not the quiet dashboard. It maps every live requirement to shipped, deferred, blocked, or waived with evidence behind each one, and it will not let a rollback trigger, action, or owner stay blank. It will not call something released, merged, or handed off without proof standing behind the claim.

Give it to your agent on a task that already has an approved plan, a finished review, and a verify artifact behind it. It will not let a good feeling substitute for evidence.

The artifact it writes down is what actually shipped, not what I meant to ship. That record is what Reflect reads first.

ship.md on GitHub Gist

Top comments (2)

Collapse
 
jugeni profile image
Mike Czerwinski

"The absence of an error is not evidence" is the sentence I'd want tattooed somewhere, because it names a failure mode that receipts alone don't fix, at least not the way people usually mean receipt. Most of what gets called a receipt, a green check, a completed run, still assumes the system under test will tell you when it's unhappy. Your provider breaks that assumption structurally: it accepts a wrong-shaped payload and stays silent either way, so there's no error channel to build a receipt out of even if you wanted one.

Which is the part I'd want spelled out more: what did Test actually produce as evidence for that specific requirement, if not the absence of an error? A schema check on the payload before it ever left your side, proving by construction that a malformed shape couldn't be sent regardless of what the provider does with it? Something on the receiving end, a delivery confirmation, a webhook, a count you can reconcile against what you sent? Or something else? The rest of the post makes clear why quiet couldn't be trusted here, but the actual mechanism that closed that one requirement is the piece I'd learn the most from, because a provider that fails silently in both directions is a harder case than a self-attesting agent. There's no internal judgment to distrust. There's just nothing coming back at all.

Collapse
 
jeelvankhede profile image
Jeel Vankhede

Fair catch, and you're right, absence of error closed nothing. What actually closed the requirement was schema validation before the payload left my side, proving by construction that a malformed shape couldn't go out regardless of what the provider did with it. The quiet dashboard at deploy told me nothing. That validation is what did.

It reads thin because the decision wasn't made at Ship. Review gives every requirement a verdict against the actual diff, not an impression, covered, partial, or missing, with partial or missing naming exactly what's short. Test either backs that verdict with a real check run and a real result, or it stays open. By the time something reaches Ship, it's resolved with evidence behind it, or it's a named, owned risk Ship inherits. Ship's job isn't to verify again. It's to refuse to call the deploy done without that evidence already on record, and to have a rollback trigger written for whatever could still go wrong live.

You're right, this is harder than a self-attesting agent. An agent gives you something to distrust. A silent provider gives you nothing to check against unless you build the check yourself, before handoff. That's why the workflow front-loads verdicts and evidence instead of leaving them for the end, Ship doesn't discover unknowns, it just refuses to move while any stay undeclared.