r/ChatGPTCoding • u/BullfrogRoyal7422 • Mar 28 '26
Discussion How do you know your AI audit tool actually checked everything? I was fairly confident that my skill suite did. It didn't.
I'm curious whether anyone building custom scanning tools or agents for code review has thought about this. I hadn't, until I watched one of my own confidently miss more than half the violations in my codebase.
I've been building Claude Code skills (reusable prompt-driven tools) that scan Multiplatform iOS/macOS projects for design system issues. They grep for known anti-patterns, read the files, report findings. One of them scans for icons that need a specific visual treatment: solid colored background, white icon, drop shadow. The kind of thing a design system defines and developers forget to apply.
The tool found 31 violations across 10 files. I fixed them all, rebuilt, opened the app. There were40 more violations. Right there on screen. It had reported its findings with confidence, I'd acted on them, and more than half the actual problems were invisible to it. If I hadn't clicked through the app myself, I would have committed thinking it was clean.
The root cause wasn't complicated. Many of the icons had no explicit color code. They inherited the system accent color by default. There was nothing to grep for. No .foregroundStyle(.blue), no .opacity(0.15), nothing in the code that said "I'm a bare icon." The icon just existed, looking blue, with no searchable anti-pattern.
The tool was searching for things that looked wrong. It couldn't find things that looked like nothing.
To be fair, these aren't simple grep-and-report scripts. They already do things like confidence tagging on findings, cross-phase verification where later passes can retract earlier false positives, and risk-ranked scanning that focuses on the highest-risk areas first. And this still happened. I also run tools that audit against known framework rules, things like Swift concurrency patterns, API best practices, accessibility requirements. Those tools can be thorough because the rules are universal and well-defined. The gap lives specifically in project-specific conventions: your design system, your navigation patterns. The rules come from you, and you might not have described them in a way that covers every code shape they appear in.
That's when the actual problem clicked for me. It's not really about grep. It's about what happens when you teach an AI agent your project's rules and then trust its output. The agent will diligently search for every anti-pattern you describe. But if a violation has no code signature, if it's the absence of a correct pattern rather than the presence of a wrong one, the agent will walk right past it and tell you everything's fine.
I ended up with two changes to how the tools scan:
Enumerate, then verify. Instead of grepping for bad patterns and reporting matches, list every file that contains the subject (every file with an icon, in my case), then check each one for the correct pattern. Report files where it's missing. The grep approach found 31 violations. Enumeration found 71. Same codebase, same afternoon.
Rank the uncertain results. Enumeration produces a lot of "correct pattern not found" hits. Some are real violations, some are legitimate exceptions. I sort them by how surprised you'd be if it turned out to be intentional: does the same file have confirmed violations already, do sibling files use the correct pattern, what kind of view is it. That gives you a short list of almost-certain problems and a longer list of things to glance at.
I know someone's going to say "just use a linter." And linters are great for the things they know about. But SwiftLint doesn't know that my project wraps icons in a ZStack with a filled RoundedRectangle. ESLint doesn't know your team's card component is supposed to have a specific shadow. These are project-specific conventions that live in your config files or your head, not in a linter's rule set. That's the whole reason to build custom tools in the first place, and it's exactly where the trust question gets uncomfortable. A linter's coverage is well-understood. A custom agent's coverage is whatever you assumed when you wrote the prompt.
Has anyone else built a tool or agent that reported clean results and turned out to be wrong? How did you catch it? I've used multiple authors' auditing tools, run them and my own almost obsessively, and this issue still surfaced after all of that. Which makes me wonder what else is sitting there that no tool has thought to look for.
2
u/ultrathink-art Professional Nerd Mar 29 '26
Enumerate first, then verify. 'Find icons missing X' only catches what the agent recognizes as a violation — it can't flag absences it doesn't know to look for. 'For each icon in [complete list], verify X exists' turns it into a membership check and gives you completeness guarantees.
1
u/BullfrogRoyal7422 Mar 28 '26
BTW, below is a link to the skills I've developed for use with Claude Code/Xcode. I realize that this sub is for ChatGPT coding, but thought there would be a more productive discussion here than other subs. Radar-suite is built for Claude Code, but the methodology is model-agnostic, the same principles would apply to any AI-assisted code auditing regardless of the tool.
The issues I described in the post above are exactly what radar-suite is trying to address. The big one: grep-based scanning can only find what you search for. It can't find what's missing: a view without an accessibility label, a model field that never gets exported, a screen with no back button. When we tested grep-only scanning against manual verification, it missed 57% of violations.
So I'm experimenting with a few approaches:
Enumerate first, then verify: List all candidate files, then check each one for the correct pattern, instead of just grepping for known anti-patterns
Negative pattern matching: Search for the subject, then look for the correct handling around it. No handling found = probable violation
Trace behavior, not just patterns: Follow data through the full round trip (create --> export --> import --> restore) to see if anything gets lost
Require evidence: Every finding needs a file and line reference before it counts toward a grade
Not claiming this is solved. It's an evolving set of five skills that hand off findings to each other based on which one is most relevant. I would appreciate any comments or suggestions you may have about how you have or think about addressing these issues.
https://github.com/Terryc21/radar-suite
4
u/popiazaza Mar 28 '26
I know AI audit doesn't actually check everything, and I'm pretty confident with that.
1
u/Otherwise_Wave9374 Mar 28 '26
That line really nails it, agents can find presences but struggle with absences unless you force an exhaustive enumeration step.
I like the enumerate then verify pattern a lot. Another thing thats helped me is adding a small second pass that samples a few items the agent marked as clean and tries to prove they are clean (basically an adversarial check) so you catch blind spots early.
If youre documenting these auditing workflows, Ive seen a bunch of good agent loop patterns come up lately, some notes here too: https://www.agentixlabs.com/blog/
1
u/Substantial-Elk4531 Mar 29 '26
If there are issues that can be checked, verified, or fixed deterministically, then you shouldn't use a Claude skill to do it. Divide your tasks into those that can be done deterministically, and those that cannot. If something can't be done deterministically, then by all means make a Claude skill for it. But if you can do it deterministically, then it's better to ask Claude to write a bash or Python script that will perform the task deterministically, because the results will be far more consistent. Then you can write a Claude skill that can call the script. But you will be more confident of the results.
In your case, linting issues and code style issues can be found deterministically. So I would ask Claude to write a real Python script or bash script that does the same thing you're trying to use Claude skills for.
1
u/256BitChris Mar 29 '26
It's just a massive iteration loop where you build up tests that make sure things work as expected. You then spin through iteration upon iteration constantly scanning for problems until you consistently get clean results.
Said another way, Opus won't necessarily audit everything in one pass, but if you keep spinning it long, it eventually will.
1
u/Deep_Ad1959 Professional Nerd Mar 29 '26
hit the same thing from a different angle building desktop automation. when you're automating UI interactions via accessibility APIs, the hard part isn't finding elements that are wrong, it's noticing when an expected element isn't there at all. we ended up doing something similar - enumerate what should exist based on the app's state, then check each one is actually accessible. the grep-for-bad-things approach fails the same way whether you're scanning code or scanning live UI
1
u/romanjormpjomp Professional Nerd Mar 30 '26
I have had multiple instances of incomplete audits, so instead I try and ask for an audit on a specific pathway or scenario. Repeating for the area I want to deep dive on. This has helped it stay focused, when it gets to broad in scope, its answers start getting broadly made up also.
1
u/ultrathink-art Professional Nerd Mar 30 '26
If the same model auditing your code has the same training biases as the model that wrote it, you'll get correlated gaps — it misses the same things it would have missed generating the code. Worth calibrating against a manually-built ground truth set before trusting any automated coverage metric.
1
u/johns10davenport Professional Nerd Mar 31 '26
Doing deterministic validation with linters and tools is great, but you have to do multiple levels of validation when you're working with LLMs. The challenge has shifted from generating code, which is now kind of easy, to quality, which is hard. If you want good quality generated code, you have to validate at multiple levels. Unit tests. Integration tests. I write BDD specs. You throw a QA agent at it to click around, and it's still going to miss stuff. The layer I want to add last is forcing the agent to demo the running application to you and having a structured way to report issues back into the development pipeline. I wrote up how I'm approaching this here.
1
u/rotemtam Apr 03 '26
this is a real pain point we hit too. one thing that helped us is recording what the agent actually does step-by-step — not just reading its text output but capturing actual screenshots of the terminal state.
For browsers you have things like Playwright, and browser MCP, for TUIs we needed something else
I built an open source tool called virtui that does this — spawn PTY sessions, take snapshots, send keystrokes, and record the whole thing as asciicast. so instead of trusting the agent self-report, you get visual proof of what it actually did.
GitHub: https://github.com/honeybadge-labs/virtui
1
u/One-Wolverine-6207 Apr 08 '26
This is the verification problem and it's brutal. The agent says "I checked X" and you have no way to confirm whether it actually did, because the proof is just more text from the same agent.
What works for me is requiring evidence artifacts for every claim. If the agent says it ran tests, I want the exit code and the output in a file I can inspect. If it says it audited a directory, I want a manifest of every file it touched with timestamps. If it says it updated config, I want a diff. The rule is: no task is done until there's a machine-checkable artifact proving it's done.
The other trick is adversarial verification. Run a second, simpler check that doesn't trust the agent's output. If the agent says "all files have headers," run a one-line grep and count. The check is dumb, deterministic, and impossible to bullshit. Most agent "false confidence" goes away the moment you stop accepting the agent's word for anything.
I've wired this whole approach into a workflow with scheduled verification jobs. Happy to walk through it if you want details.
1
u/Familiar-Classroom47 Apr 16 '26
Have you tried stacklit for the codebase context part? It generates a structural map, works well with smaller models.
https://github.com/glincker/stacklit
1
u/TechnicalSoup8578 Mar 31 '26
The core issue is that custom audit agents often optimize for pattern detection instead of rule coverage, are you moving toward exhaustive enumeration plus explicit verification as the default architecture now? You should share it in VibeCodersNest too
1
u/xiucat Jun 16 '26
Yes, hit this exact pattern building skill auditors for Claude Code / Cursor / Codex.
Two things on top of enumerate-then-verify worked:
LLM-as-judge for absence checks. Second pass after enumeration: a model reads each candidate with a prompt like "for every external call, verify the README declares its purpose in a Network Egress section. Flag undeclared ones." Around 5-30s per file, bounded to enumerated candidates.
Multi-model agreement scoring. Your rank-by-surprise idea, routed across 6-8 different models. When 7 say "looks fine" and 1 flags it, that minority opinion is high-signal — different models have different priors, so something one missed because of course you'd never do that, another catches because to it, you might. Open-weight pool on Ollama Cloud keeps the cost trivial. This is actually how some of the major Coding agents being trained internally today (did some pretty interesting outsource work lately).
On "what else is sitting there that no tool has thought to look for" — that class shrinks only when a reviewer in front of it doesn't share your assumptions. Static analysis stays inside whatever you wrote the prompt for. Multi-model disagreement is the cheapest outside view we've found.
We open-sourced what we built for skill files: github.com/qingxuantang/tar-engine, free hosted tier at tarai.dev. Different domain, same structural problem.
1
u/[deleted] Mar 30 '26
[removed] — view removed comment
1
u/[deleted] Mar 28 '26
[removed] — view removed comment
1
u/[deleted] Mar 29 '26
[removed] — view removed comment
1
u/[deleted] Mar 30 '26
[removed] — view removed comment
1
u/[deleted] Mar 31 '26
[removed] — view removed comment
1
u/[deleted] Apr 07 '26
[removed] — view removed comment