CopperSunDev

Ten developers using AI assistants don't produce one coherent codebase. They produce ten coding styles, ten prompt strategies, and ten different vulnerability surfaces — then merge them into one repo. The failures aren't random. They're structural: each developer's AI assistant has its own generation habits, its own blind spots, and its own non-determinism. What catches the gaps isn't another AI reviewer. It's a scanner that runs the same rules on every PR, every time, regardless of who wrote the code.

Why Individual Vibe Coding Habits Don't Aggregate

BrassCoders treats every developer's code the same way: it runs 12 static-analysis scanners — Bandit, Pylint, Pyre/Pysa, Semgrep, ast-grep, detect-secrets, and six custom detectors — and emits the union of their findings as YAML. The developer's name doesn't appear in the output. The AI assistant they used doesn't appear. What appears is the vulnerability pattern, the file path, and the scanner that caught it.

This matters because vibe coding habits don't cancel each other out at team scale. One developer prompts their AI assistant to be conservative with dependencies. Another prompts theirs to ship fast. A third uses a different model entirely. Each of these produces code with different structural properties. Some AI assistants tend toward certain SQL construction patterns. Some miss exception-handling edge cases in ways others don't. None of this averages out when you merge. Each developer contributes their AI assistant's specific blind spots to the shared codebase.

The aggregate vulnerability surface isn't the average of ten developers' risks. It's the union. Every blind spot any AI assistant has becomes a potential hole in the codebase.

Non-Determinism Compounds at Team Scale

BrassCoders is offline and deterministic: the same scanner version on the same code produces identical YAML output every run. No sampling, no temperature, no prompt variation. This is a documented property of static analysis — the scanner reads the AST and applies fixed rules.

AI assistants work the opposite way. GitHub Copilot, Claude Code, and every other LLM-based coding assistant generate suggestions probabilistically. Per the model documentation for every major provider, LLM outputs vary across calls even with identical inputs — temperature and sampling are how these models work. A developer who accepts a Copilot suggestion on Monday and re-prompts on Tuesday might get meaningfully different code for the same function signature. Security properties can change between those two suggestions.

Scale this to ten developers across a sprint. Each developer is accepting suggestions from a non-deterministic system. Different prompts, different temperatures, different context windows. The security properties of what they ship aren't predictable from the properties of what they tested. And if your code review is also LLM-based, you've added a second non-deterministic layer on top of the first.

The gap between what a developer's AI assistant generates and what a deterministic scanner sees is where bugs live. An AI reviewer is great at detecting things it's seen in training data. A static-analysis scanner applies rules that don't change based on what the model saw last week.

What One Consistent Gate Buys the Team

BrassCoders running in CI means the same rules run on every PR — regardless of which developer pushed, which AI assistant they used, or what their local review habits are. The findings set is the scanner's findings set. Not one developer's intuition, not one AI assistant's opinion. The rules.

This is the property that makes BrassCoders a team-level gate rather than a per-developer preference. A per-developer preference is skippable. A CI gate isn't. When SQL injection looks the same to Bandit whether it was written by GitHub Copilot or Claude Code — because it matches the same AST pattern either way — the scanner catches it regardless of its origin.

The other thing consistency buys: auditability. When your scanner produces the same YAML for the same code, you can compare runs over time. A finding that appears in PR #47 and is still present in PR #52 is a finding that wasn't addressed. A finding that disappears between commits was either fixed or suppressed — and BrassCoders tracks which. An LLM reviewer can't give you that. Two runs of the same LLM reviewer on the same PR produce different outputs. You can't diff them.

The CI Integration Path

BrassCoders plugs into GitHub Actions as a single workflow file — one scan step, same rules, every PR, no per-developer configuration. Teams that want findings caught before they push can also add a pre-commit hook that runs the local scanner before git commit completes.

The full GitHub Actions setup is documented at add-brasscoders-to-github-actions, and the pre-commit hook setup is at pre-commit-hook-ai-coder-bugs.

The split matters for team dynamics. Pre-commit scanning is optional — a developer who doesn't install the hook still gets caught at CI. CI scanning is mandatory — every PR hits the scanner before it can merge. Teams with high autonomy and low process overhead can start with CI only. Teams where developers want earlier feedback add the pre-commit layer on top.

Either way, the CI gate is where consistency lives. It's the one scan that runs on everyone's code under the same conditions.

One activation covers 3 machines per license. A developer can run BrassCoders on their laptop, a staging box, and a CI runner if they want to count the runner as an activation — or the team can run the CI scan under a shared license. The BrassCoders Paid plan is $12 per developer per month.

What Team-Wide Findings Look Like

When BrassCoders scans a shared codebase after a two-week sprint of AI-assisted development, the findings YAML reflects the aggregate of all 10 developers' contributions. No single developer's code is labeled. The finding at line 147 of auth.py is either a hardcoded secret or it isn't. The SQL construction in db_utils.py either hits Bandit's B608 injection rule or it doesn't.

This flat view of findings is a feature, not a limitation. A finding that only shows up in one developer's code isn't "their problem" — it's a gap in the shared codebase. Treating it as theirs individualizes what should be a shared signal. The scanner doesn't know who wrote the code. The security reviewer — a human or an AI assistant doing triage — shouldn't have to either.

The determinism argument is covered in depth here. The short version: a gate that produces different outputs for the same inputs isn't a gate. It's a suggestion.

For teams running 10 developers through a sprint of AI-assisted development, the question isn't whether any individual developer will write a vulnerable function. One of them will. The AI assistant will generate something plausible and slightly wrong, and the developer will accept it. The question is whether the team has a gate that catches it before it merges. BrassCoders in CI is that gate.

pip install brasscoders
brasscoders activate
brasscoders scan .

Enter fullscreen mode Exit fullscreen mode

Start with the OSS core, free, Apache 2.0. Add BrassCoders Paid when you want the noise-reduction pass that brings 1500+ findings down to the actionable ones.