← Skills

release-gate

release-gate

When an agent or user needs to know whether something is actually shippable, or why a release is being held. Also use when the user says "can we ship this," "is this live," "did that deploy," "why isn't my fix in prod," "are we green," "ready to release," or "what's blocking the deploy." Use this whenever the gap between "the code is written" and "the thing is live" is the question. For probing a surface for holes, see security-audit. For a broken production, see incident-response.

Release Gate

You hold the line between the cycles are done and the thing is live. Those
are different facts, and this estate has paid for the gap repeatedly: a plan
closed 10/10 with a RED kill-switch; a branch green at 12/12 that went red on
70 assertions the moment trunk merged in; security fixes sitting on main for
weeks while the workers ran the old code.

Cycles done ≠ releasable. Green locally ≠ green in prod.

The five gates, in order

# Gate Passes when
1 Green locally The FULL lane (bun run verify), not fast. deploy.sh exports FULL_VERIFY=1
2 Trunk merged in main merged into the branch and re-run — trunk gates are a second, invisible acceptance test
3 Deployed wrangler deployments compared to git log. A worker runs what it was last deployed with
4 Green in prod Probed live, from where the code runs, and the run ended on the path asked for
5 Docs true The runbook describes what shipped, not what was planned

Gate 0 runs before gate 1: the tree and its generated artifacts. .release/
must be clean (release.sh promote exit 6 otherwise), and deploy.sh step 0.5
refuses a drifted block manifest before any test runs — regenerate with
node .claude/scripts/blocks-manifest.mjs and commit all three artifacts.

Gate 1 has two lanes and two doors that weigh them differently. deploy.sh
treats the typedb lane as non-blocking and prints ✓ gates green over a red
one; release.sh promote needs a green stamp for both lane keys and exits 3
without one. Only promote exit 0 is a receipt. A WAIVED as TypeDB outage run
stamps nothing. Measured 2026-09-13: three green --gates-only runs, three
promote refusals, one sha.

A held release names which gate bit and the coordinate — gate 3, which
worker, which deployment sha. A held release is not a failure report; it is a
location.

Gate 4 has a trap worth stating alone

A route counts as proven only if the run ended on the path asked for. A
signed-out /u/<slug>/* 302s to /signin, which renders 200 with no console
errors — that scored "ok" for months while every authed clause was silently
being verified against the login page.

The couplings no single config reveals

Check these before gate 3 passes; each is shared state one worker's config
cannot show you:

  • CALLBACK_SECRET — byte-identical in api/ and channels/
  • IDENTITY_SECRET — byte-identical in channels/ and the web worker
  • SERVER_SECRET — byte-identical in one.ie/web and pay/
  • A cron handler whose expression is absent from that worker's [triggers] crons is dark — registering the job in code is not enough.

Hard rules

  • Never report a fast pass as a full pass, or a green branch as a green
    release. Name the lane and the gate every time.
  • A reused gate is reported as reused. Two gates memoise on a byte-identical
    tree — the full suite and the astro build.
  • Do not route around the refusal. An unpaid deferred-pin debt REFUSES a
    deploy that did not run the suite. That refusal is the feature.
  • A five-minute cache can make a correct release look broken. Check the TTL
    before rolling back something that just shipped.
  • Deploys are outward-facing — confirm before shipping unless this specific
    release is already authorised.

Cannot run

A gate that is ABSENT is the worst of the three states — worse than a red,
because a red stops the release and an absent one reads like a pass. A gate that
could not run is the answer, not a gap in the answer.

Say cannot-run, naming the gate, when a check could not execute at all: the
tool is not installed, the probe could not reach production from where it ran,
wrangler could not be asked what is live, or the tree moved under a cached
result. Return { ok: false, gate: "<which>", reason: "<why it could not run>" }
and close with warn. Four gates green and one unrun is not four-fifths of a
release; it is a release whose state is unknown, and it does not ship.

Out of scope

  • Running the deploy — the operator ships; this gate says whether they should.
  • Fixing what gate 1 caught — that goes back to the author.