The release was one “safe to ship” vote away from landing with a save path that did not save what the UI claimed.
That was the uncomfortable result of a review cascade we have been using on release work. The cascade is our internal review, then Manus, then Codex. On paper that looks redundant. In practice it produced two very different kinds of catches.
In the first review, the cascade found a missing server side permission check and an edit that was not transactional. In the second, most of the reviewers agreed the change was safe to ship. The one reviewer that could read the actual files disagreed. It found a real save path bug the others missed because they trusted an overconfident summary.
What separated the two outcomes was whether a reviewer could trace the behavior from the request through the code that persisted it. Model personality and the number of opinions in the room did not decide it.
Four “safe to ship” verdicts, one unverified premise
We do not run release review as a single approval gate. A change moves through the internal review and then through Manus and Codex. The point is to force competing reads of the change before we ship, and asking several systems to restate the same description does not do that.
The input a reviewer gets shapes the review. A summary can say an edit saves correctly. A diff summary can say permissions are handled. Both can be honest descriptions of intent, and neither proves the path is correct.
The release with the save path bug showed the failure mode cleanly. The reviewers without file read access had a coherent account of the change: the save flow was implemented and safe. It was concise, confident, and wrong in the only way that mattered. The reviewer that could read source followed the actual save path and found the bug.
Agreement did not repair the missing evidence. Several reviewers can independently accept the same persuasive summary, and that is one unverified premise copied several times. A stack of “safe to ship” verdicts feels like strong evidence. It isn’t when everyone issuing them is looking at the same abstraction layer.
The first release: a permission check and a transaction
The other review made the same point from the opposite direction. This time the cascade caught two concrete problems: a missing server side permission check and a non transactional edit.
The permission problem was not a visual defect. The interface could show the right controls and the happy path could work. But a permission decision that exists only in the client is not a permission boundary. The server has to enforce the rule at the point where it accepts the change, or the application is relying on the screen instead of the system of record.
The non transactional edit was a different class of risk. An edit that touches related state needs an all or nothing outcome. Without a transaction, part of the work can persist while a later step fails. The user sees an edit attempt, and the database can end up holding an incomplete version of it.
The two findings were useful because they were not variations of the same complaint. One asked whether the server could reject an unauthorized request. The other asked whether the edit could leave related state half changed. The cascade exposed both questions before release.
We also looked at a simpler workflow: let the internal reviewer handle the code and use Manus and Codex only for a final sanity check. We rejected it because it turns the outside reviews into a confidence ritual. They need a real chance to find something the first pass missed.
We also considered treating the consensus review as the final authority. The save path bug ruled that out. Consensus is useful evidence, but it does not substitute for a reviewer who can inspect the source that creates the behavior.
What each reviewer had to answer
A useful review result has to explain how it got there. “Safe to ship” does not say what was checked. “Bug found” is not much better if the reviewer cannot connect the bug to the code path that causes it.
For the missing permission check, the question was direct: where does the server decide whether this request is allowed? If the answer is only a client control, the review is not finished.
For the non transactional edit, the question was just as concrete: which persistence steps belong to one operation, and what happens if a later step fails? With no transaction around related writes, an incomplete state is waiting to happen.
For the save path bug, the question was simpler still: what file receives the saved value? The summary supplied one answer. The source supplied a different one. Only one of them was running in the release.
That sequence is the part we want to keep. We observed a confident approval. We compared it with a review that had direct file read access. We traced the claimed behavior through the actual save path. The disagreement was not a matter of opinion, because the code resolved it.
This is why we are wary of review systems that optimize for polished conclusions. An overconfident summary removes the reviewer’s urge to verify, and the cleaner it sounds, the easier it is to mistake for an implementation trace.
What changed in the cascade
Giving a reviewer source access does not guarantee the reviewer is right. It gives the reviewer the ability to test a claim against the implementation instead of against a retelling of it.
That is a different job. A summary reviewer asks whether the described approach sounds reasonable. A source reviewer asks whether the route, permission boundary, edit sequence and save path match the description. Both are valuable, and they should not carry the same weight.
We still run the internal plus Manus plus Codex cascade, and we still want independent passes because the permission and transaction findings show what multiple passes can uncover. But every release review now needs at least one reviewer with real file read access, and that reviewer’s diagnostic path has to be visible.
A release is safer when one reviewer has read the code that will run, traced the behavior that matters, and can show the rest of us where the summary stopped matching the source. In our case that was the one reviewer with file access, and it was the one that found the save path bug.