One maintainer, one agent and 141 PRs with no human review: do automated controls replace review or just disguise it?
In our article on verification debt we left a case open: a production repository with a single maintainer, automated controls in place, and not one PR reviewed by another person. The question was uncomfortable: do automated controls replace human review, or do they just disguise its absence?
That repository is ours: the Dixi-Project platform (website, courses, support, admin panel and API). This article covers its first thirty days with every PR going through a pipeline, using the real data: what the controls stopped, what slipped past them, and what we cannot measure. It includes what went wrong.
The short answer: they do not replace review, but they are not a disguise either. They replace the procedural part (was the process followed?) and not the judgment part (is this change right?). The risk of disguise appears when a green check is read as if it answered the second question.
The case
From September 17 to October 17, 2026:
| Indicator | Value |
|---|---|
| PRs merged | 141 |
| PRs reviewed by another person | 0 |
| People who merge | 1 |
| Commits co-authored by AI | 236 of 268 (88%) |
| Median time from opening a PR to merging it | 6 minutes |
| PRs merged in under 10 minutes | 82 (58%) |
| Median size, in lines of code | 66 (90th percentile: 395) |
| Deployment runs across the six pipelines | 210 |
There is no review by another person because there is no other person: this is single-maintainer mode, an exception recorded in an architecture decision. The check that requires approval from someone other than the author is in warning mode until January 2027.
The controls that do exist
Each control is a mechanism that fails on its own, not a good intention:
- Before the agent acts: the agent cannot read secrets, edit already-approved tests, sign commits, tick the accountability box, merge PRs or approve deployments. Hooks that inspect every action prevent it. A person does all of that.
- Before calling something done: the agent cannot declare a task finished while local verification is red (test suites, documentation validation, the hook matrix).
- After the merge, at the pipeline's Gate: it checks that the commit comes from a PR, that tests pass, that there are no new dependency vulnerabilities, no secrets and no new static-analysis findings, plus the human-accountability check: attestation box ticked, commits signed off by the person, a maximum size and, if the PR touches the Gate itself, a two-hour wait between the last change and the merge.
- Before production: a manual approval that compares the waiting revision with the latest commit on the main branch.
One design detail matters: because of limits in the continuous integration service, the Gate runs after the merge. A PR that fails stays on the main branch, but it is not deployed.
What the controls stopped
Of 210 deployment runs, 65 were stopped. Behind them are 31 distinct revisions, because a single merge triggers several pipelines.
| Cause | Runs | Revisions |
|---|---|---|
| Gate: human-accountability check | 12 | 4 |
| Gate: September, no log available | 26 | 10 |
| Build or deploy failure | 10 | 8 |
| Manual approval rejected or expired | 9 | 5 |
| Gate: secrets configuration error | 5 | 1 |
| Gate: dependency audit tool failure | 3 | 2 |
The four merges stopped by the human-accountability check:
- Two PRs that changed the Gate itself were merged before the two-hour wait. The check rejected them, and they were not deployed until a later PR complied.
- One PR with three commits missing the person's sign-off.
- One PR without the attestation box ticked and without sign-offs.
What is worth noticing: all four rejections were about process, not code. The Gate did not find a defect in any of those changes; it found that the procedure had not been followed. The other causes are infrastructure failures or failures of the tool itself. The September logs are no longer available, so we do not know what stopped those 26 runs.
What slipped past them
These problems reached production or were found some other way. We describe them without details that would compromise security:
| Date | What happened | How it was found | What changed afterwards |
|---|---|---|---|
| Sep 16 | Direct URLs on two of the sites opened the home page instead of the right page, including the password-recovery link students receive | By using them | The missing rule was configured in the content delivery network |
| Sep 17 | An old run waiting in the queue was approved, and older code was deployed twice | By checking what was deployed | A script that compares the waiting revision with the latest commit before approving |
| Sep 21 | A pipeline finished green but did not publish the component everyone assumed it did | By noticing the change was missing | Documented; that component is published through a separate procedure |
| Oct 7 | Files were lost from a storage bucket, with no copy and no record of who deleted them | By not finding them | Versioning with 90-day recovery |
| Oct 10 | File uploads from the admin panel failed because of a missing configuration | By trying to upload | The configuration was restored |
| October | Server dates were shown 6 hours ahead | By looking at the dates | A single function for reading server dates in all three applications |
| Oct 17 | The runner for a blog experiment did not record certain failures and over-reported results | A result that did not add up | Fixed and the analysis was rerun (we wrote about it here) |
Two patterns:
- Almost none was a defect visible in the PR's diff. They were infrastructure configuration, operational state or manual steps. A line-by-line code review probably would not have caught them either. The exception is the dates, which were in the code.
- Several controls were born from an incident. The approval script exists because on September 17 the wrong thing was approved. That is a healthy improvement pattern, but it also means the control system runs one step behind the problems.
What is measured and what is not
| Claim | Status |
|---|---|
| No PR was reviewed by another person | Measured |
| The automated controls stopped real deployments | Measured: 4 merges on accountability grounds, plus infrastructure failures |
| The controls found code defects | Not observed in the rejections with logs available |
| The problems that slipped through would have been caught by human review | Cannot be known; most were not in the code |
| The maintainer reviews every PR | Not measured: the box says so, and a 6-minute median leaves little room |
| Hooks prevented agent actions | It happened, but how often is not recorded |
Rival explanations
- Review happens before the PR. In this workflow, the person works with the agent in the same session: reading, asking for changes and testing before the PR is opened. The 6-minute median measures the paperwork, not the review. That is plausible, and it is exactly what the attestation box is meant to capture, but it leaves no evidence a third party can verify.
- Selection. Some PRs are blog content, documentation or minor tweaks. The average risk of a PR in this repository is lower than in a payments system.
- Displacement. Verification did not disappear: it moved to the Gate, the tests and the production approval. That is true for the process, and not for the judgment about whether a change is right.
So, replace or disguise?
They replace the procedural part. They guarantee that nothing is deployed without sign-off, without attestation, with red tests or with exposed secrets, and that nobody skips the wait when touching the control system itself. That part works, and the four rejections show it.
They do not replace judgment. No control asks whether the change is the right one, whether the production configuration matches what everyone believes, or whether what was deployed is what was meant to be deployed. What slipped through lived exactly in that space.
They can disguise when a green Gate is read as if it answered those questions. Our own experiment runner showed it on a small scale: it reported green on what it had not checked.
What we would change
- Post-deployment verification. Several failures would have been caught by a test against what was deployed: does the direct URL open its page? Is the published version the one from the commit?
- Log what the hooks stop. Today we know they work, but not how often or what they prevented.
- Sampling audits. Pick a few PRs at random each month and review them cold, with time, to estimate how much slips through instead of assuming it.
- Split by risk. For high-risk changes (money, personal data, authentication), a second review, even by someone external, or at least by a different model, as the common-cause experiment suggests.
- Keep the logs. We lost September's; without them, the first month cannot be audited.
What this article does not claim
- It does not claim a single maintainer is good practice. It is a recorded exception, with a date to stop being one.
- It does not claim automated controls are enough. It claims they cover the procedure and that judgment is still uncovered.
- It does not claim human review would have prevented the incidents. Most were not in the PR's code.
- It does not generalize. It is one repository, from one team, over one month.
Sources
- PR and commit history of the repository, retrieved October 17, 2026.
- Execution history of the six deployment pipelines and logs of their Gate stage, retrieved October 17, 2026. The September logs were no longer available.
- The project's own incident and decision log.
- Dixi-Project: Verification debt, Scope, specify, audit, Teaching software engineering when AI writes the code and Do AI-written tests catch AI-written bugs? (2026).