DEV Community

Andréas Bodin
Andréas Bodin

Posted on

Can your verify gate actually fail?

I let Claude Code commit directly to my repositories. I don't review the diffs. I didn't think I needed to, because I built a deterministic verify gate — a script that lints, typechecks, builds, and runs tests. If the gate goes green, the PR merges automatically.

I trusted that gate implicitly. Until I actually sat down and asked the one question that matters: If an agent pushes completely broken code right now, will this gate actually go red?

Not "is the script configured?" Not "does the file exist?"

Will it actually fail?

Turns out, for three out of my four repos, the answer was an emphatic no. The gate was returning GREEN without running a single line of code.


The line of code that lied to me

My gate script is repo-agnostic. It looks up the repository name in a policy JSON file (gates.<repoName>) and falls back to a default if it doesn't find one.

Here is the PowerShell logic driving the whole operation:

$steps = $policy.gates.$RepoName
if ($null -eq $steps) { $steps = $policy.gates.default }
if (-not $steps -or $steps.Count -eq 0) {
    Write-Log "GREEN (no gate steps configured for '$RepoName')"
    exit 0                       # <-- Unconditional green
}
Enter fullscreen mode Exit fullscreen mode

And here is my config file:

"gates": {
  "app": [
    "npm run lint",
    "npm run test",
    "<design-gate script>"
  ],
  "default": []
}
Enter fullscreen mode Exit fullscreen mode

Look at that exit code. If a repo doesn't have an explicit entry in the JSON file, it falls through to default: []. The script sees zero steps, prints GREEN, and exits with 0.

The runner sees exit code 0 and instantly merges the code. I built a system where having no tests configured is structurally identical to passing all tests.


The Audit: 4 Repos, 1 Real Gate, 0 Peace of Mind

When I audited all four repos the runner is allowed to touch, the reality was pretty grim:

  • app (The Runner itself): The only gated repo, but it's full of holes. npm run lint runs, but tsconfig explicitly excludes the runner/ directory — meaning 51 files of core executor code are never typechecked. Next.js build isn't in the gate at all, so client/server boundary breaks ship freely. Vitest runs 28 test files, but the glob pattern completely misses *.test.tsx files.
  • product (Next.js app): The most embarrassing row. It has full ESLint, tsc --noEmit, vitest (10 suites), and next build ready to go in package.json. None of them were wired into the gate config. It had 0% coverage purely because of lazy config debt.
  • notes (Markdown vault): Unconfigured. It doesn't need npm, but it does need a basic script to check for broken wikilinks or bad frontmatter. Instead, it was just auto-approving everything.
  • portfolio (Vite site): Unconfigured and the directory wasn't even a valid Git worktree. Jobs were dying before the gate even executed, but if they had reached it, they would have passed instantly.

How to fix a fake gate

The real bug here isn't missing npm scripts. The structural flaw is that an empty gate defaults to success.

To fix this properly:

  1. Make empty gates loud. If $steps.Count -eq 0, the script must exit non-zero or return an explicit UNGATED status. A missing key should break the build, not bypass it.
  2. Wire up the low-hanging fruit. The product repo was fixed with a single line in policy.json.
  3. Add actual build checks. Typechecking doesn't catch bundler or framework errors. Adding npm run build to the gate costs execution time, but it's the only way to catch real deployment breakers.
  4. Fix silent exclusion traps. Un-exclude critical core directories from tsconfig and fix the Vitest globs before someone writes a .tsx test that never actually gets executed.

If you run AI agents against your codebase without reading the diffs, go break a file on purpose and run your gate. If it doesn't yell at you, you don't have a safety gate — you just have a script that automatically approves bad code.


I'm Andréas — full-stack dev, CTO at a B2B SaaS, building my own agent tooling. Portfolio: https://andreas-bodin.vercel.app

Top comments (0)