Library

The reviewer rejected my fix twice. Both times it was right.

Read as
working implementation · tests

The release had passed more than 1,700 tests.

The production build was green. The changed screen looked right on staging. The data had moved through the parser, development database, verification job, API, and browser. Then I gave the production diff to a review agent with one instruction: review it as if the builder's summary did not exist.

It blocked the release.

I fixed what it found, sent the new diff back, and it blocked the release again. Both findings were real. Neither was a normal code bug. They were bugs in time.

Green described the final state

The application depended on a new coarse-grained dataset and cached its read model. Staging proved this final state:

data exists
schema exists
code is deployed
cache contains a valid result

Production deployment is a sequence:

schema workflow starts
data workflow waits for approval
application deploy starts
application reads the new table
cache stores the result
data workflow finishes

In that sequence, the application can run before its dependency exists. A tolerant query can return an empty result rather than an error. The app then caches the empty result. The data arrives ten minutes later, every workflow turns green, and the product stays wrong until the cache expires.

No final-state staging test catches this. The first review finding was simple: data had to lead code, and the production deployment did not enforce it.

My first fix still described one push

I added a gate. If the current push changed the data or schema paths, the deployment would wait for the prerequisite workflow.

if git diff --name-only "$before" "$current" | grep -q '^pipeline/'; then
  wait_for_data
fi

The reviewer simulated two pushes.

Commit A changes the data contract and starts a human-approved pipeline. While it waits, commit B changes unrelated copy. The deploy for B checks only B's diff. B did not touch pipeline/, so it skips the gate and deploys code containing A.

The prerequisite is in the ancestry of B, but not in B's local diff. My gate knew what changed in one event. It did not know which obligations the release inherited.

A release obligation belongs to ancestry

The corrected gate asks three questions:

  1. What is the newest commit in this release ancestry that changed the dependency?
  2. Has the prerequisite workflow succeeded at that commit or a later commit?
  3. Is that successful workflow commit itself an ancestor of the release?

The core proof is two graph queries:

git merge-base --is-ancestor "$required_sha" "$workflow_sha" \
  && git merge-base --is-ancestor "$workflow_sha" "$release_sha"

The first condition says the successful run contains the required data change. The second says the release contains the successful run's commit. Together they reject a green run from before the change, from an unrelated branch, or from a future commit.

The reusable release ancestry gate includes the negative path test.

The reviewer needed a different job

This was not about one model being smarter than another. The useful difference was role.

The builder's job was completion. It held the ticket, implementation decisions, test results, staging behavior, and the chain of reasons the solution made sense. The reviewer received a smaller context:

Here is the production base.
Here is the proposed head.
Here is the acceptance criterion.
Find a sequence in which this can still be wrong.
Do not implement. Report first.

That prompt changes the search space. Instead of asking whether the code matches the intended design, the reviewer tries to construct a counterexample.

I turned the role into the reusable Review a production change skill. The important instruction is not “review carefully.” It is “prioritize temporal and lineage risks, and derive at least one oracle independently from the author.”

Tests approve examples. Reviewers search for sequences.

The test suite still mattered. It proved parsing, suppression handling, mapping, verification, UI selection, accessibility, and unrelated behavior. The mistake would be asking it to prove something outside its model.

A typical test arranges one state, performs one action, and checks one result. The release bug needed a timeline:

T0 dependency change merges
T1 prerequisite workflow waits
T2 unrelated change merges
T3 deploy logic evaluates only T1..T2
T4 application deploys inherited code

Once written down, it looks obvious. Before review, it was hidden inside green workflow boxes.

The production path now has four proofs: the builder proves implementation, staging proves the deployed user path, an independent reviewer tries to falsify the rollout, and the human owner decides whether to approve production.

One system makes the release reach the desired state. The other asks whether users can be harmed on the way there.

Public discussion

Questions, corrections, and useful disagreement

Moderated on GitHub ↗

Sign in with GitHub to join the conversation. Comments are public. Article views are anonymous and counted once per browser, per article, each day.