On bespoke software, AI, and earning trust back

Whether your codebase was hand-crafted, coded over perhaps a decade, or generated by an AI assistant last quarter, the trust problem underneath it is the same one, regardless. It gets solved the same way: measured, not promised.
Hard data over handwaving.
On delivery, code quality, and what AI is actually good for
Walk into almost any mid-sized or large business today and you’ll find, somewhere beneath the brand and the balance sheet, a piece of software nobody outside the company has ever seen. Perhaps it routes the sales team’s leads, calculates payroll adjustments, reconciles the ledger against the bank feed, schedules the technicians, matches the inventory to the orders. It was built, at real expense, specifically for this business, because nothing off-the-shelf quite did what the business needed. The jobs to be done by the software were specialised and unique.
That bespoke software is now load-bearing. Pull it out and the business doesn’t just get slower. In a lot of cases, it stops completely. That means every business running on custom-built systems has, whether it meant to or not, placed a very large bet: a bet that the software is good enough, reliable enough, and maintainable enough to keep carrying that load, quarter after quarter, as the business changes around it. Now, the system doesn’t just support the business, it very much is the business. For some stakeholders, that can be an uncomfortable realisation.
For a long time, a lot of us have been quietly anxious about that bet. Not because anyone expects perfection — every serious technologist knows software is never finished, only shipped — but because the size of the bet keeps quietly growing, while the confidence behind it often doesn’t. As the company grows, more of the business runs through the custom code every year. More revenue, more customer data, more regulatory exposure sits behind systems that were built under heavy deadline pressure, by whoever was available at the time, and maintained since, by whoever inherited them.
The trust problem nobody named
Even before anyone had heard the term “vibe coding”, plenty of that bespoke software was already in trouble — not broken exactly, but fragile in ways everyone around it could feel and nobody quite wanted to name out loud. Not a crisis, but risky. The business kept running on it and everyone was grateful for that.
Bug backlogs grew long enough that teams stopped reading them end-to-end. It was impossible to do so. Features that had been promised, half-built, or built and then misunderstood by the people using them, or else misunderstood by the people coding them, sat in the grey zone between “known issue” and “low priority” Housekeeping — the unglamorous work of tidying dependencies, retiring dead code, keeping documentation honest, keeping up to date with libraries and dependency patches — lost every fight for priority against the next deadline. Attending to the infrastructure simply made the rate of “feature and fix” flow seem way too slow.
None of this happened because the developers involved were careless. It happened because coding standards varied wildly from team to team, and sometimes from person to person within the same team. Also, because a lot of the software industry’s genuinely well-established best practices — disciplined code review, meaningful test coverage, documented architecture decisions, basic threat modelling — quietly didn’t get applied. Not from ignorance alone, though that was sometimes part of it. Mostly it was the much more mundane trio: pressure of time, unawareness that “properly” was even an option on this budget, and cost. Best practices seemed like a “nice-to-have” overhead.
The uncomfortable truth is that a lot of businesses running on this kind of software were getting away with it. Not comfortably — only just. By the skin of their teeth.
Underneath the surface: poor maintainability, code that resisted extension without breaking something else, reliability that depended on nobody touching the wrong file at the wrong time, and performance that degraded a little more with every release. Vulnerabilities sat unpatched. Privacy and security deficiencies went unaudited, because auditing them cost money and time, which nobody had budgeted for.
Stakeholders felt this, even when they couldn’t name it precisely. Trust in the software eroded — slowly at first, and then all at once when something broke publicly. Frustration mounted: why can’t the team just get on top of this? It was a tension that had been building for years, waiting for something to either resolve it or make it dramatically worse.
Part of what made it so hard to fix from the inside is that none of this shows up as a single decision anyone made. Nobody sat in a room and chose to ship insecure code, or to let a critical feature go misunderstood, or to skip the tests. Each individual shortcut was locally reasonable — a fair trade against a real deadline, made by a competent person doing their best with the time and budget they were given. It’s only in aggregate, over years, that those reasonable trade-offs compound into a system nobody fully trusts and nobody has the appetite to properly excavate.
Then vibe coding arrived
AI-assisted coding — “vibe coding,” in the term that stuck — looked, for a moment, like the resolution stakeholders had been waiting for. Here, finally, was an alternative to imperfect human development teams: a way to generate working software quickly, without needing to find, hire, and retain the scarce, high-priced senior engineers who might have fixed the backlog properly in the first place.
It’s an appealing pitch. Development teams are expensive and hard to grow. Good engineers are in short supply and command premiums that strain small and mid-sized budgets. If an AI system could simply produce the software — quickly, cheaply, on-demand — a lot of long-standing organisational pain would simply dissolve. Features and fixes would flow at the speed required by stakeholders.
In practice, it didn’t work out that way. Code generated straight out of the box by vibe-coding tools was, on the whole, decidedly worse than what the human teams had been producing — the same human teams whose output had already been a quiet source of anxiety. The AI coding tools didn’t close the trust gap. In a lot of codebases it widened it: duplicated logic, no clear architectural layering, invented dependencies, security patterns applied inconsistently or not at all, tests that passed because they tested nothing meaningful. The failure modes were different from the old human failure modes. They weren’t smaller.
Some of that gap is a fair criticism of the tools as they stood: models generating code with no real memory of the business rules embedded three modules away, no felt sense of which shortcuts were load-bearing and which were cosmetic, and a strong tendency to produce something that looked plausible and complete rather than something that was actually correct. The tools lacked object permanence. But some of it was simply the mismatch between what vibe coding was being asked to do and what it was ever likely to be good at. A tool that generates code quickly, on request, with no persistent institutional memory of the codebase’s history, was never going to replace the accumulated judgement of an engineer who had been living inside that system for years — it was only ever going to replace the parts of software development that were mechanical in the first place.
So businesses that had gone looking for a way out of an already uncomfortable position often found themselves somewhere worse: sitting on bespoke software that combined the legacy trust deficit of the old human-written system, with a fresh layer of AI-generated fragility on top — produced faster than anyone had the capacity to review it.
Four ways out, and only one of them new
That left a fairly narrow set of realistic options.
- Get better coders. Senior engineers who can both write good software and clean up what already exists. This is the most reliable fix, over time, and the hardest to execute — that talent is scarce, expensive, and difficult to retain once you’ve found it, especially against competitors who can pay more, or offer more interesting problems.
- Scrap bespoke software altogether. Retreat to off-the-shelf tools and accept whatever compromises that entails. For some businesses, this is genuinely the right call. For a lot of others, the bespoke system exists precisely because no off-the-shelf product does the specific thing the business needs done — and giving it up means giving up the operational advantage it was built to provide.
- Limp along. The option most businesses default into by inertia rather than choice: keep running software that isn’t adequately supporting the business, keep patching the fiercest fires, and keep hoping the gap between what the software does and what the business needs doesn’t widen into something catastrophic. But hope is not a strategy.
- Do something authentically innovative, if you can find it — something that doesn’t require an unaffordable hiring spree, doesn’t require abandoning the bespoke investment, and doesn’t just mean tolerating the status quo for another year.
Measuring trust instead of guessing at it
Here’s a version of that fourth option worth taking seriously: use standard, well-established code quality tooling to evaluate a codebase objectively, and turn the results into something a non-technical stakeholder can actually read — a live, evidence-based picture of how trustworthy the software really is.
Not a vague reassurance from the development team that “it’s mostly fine”, taken at face value. An actual measurement, refreshed as work continues, showing exactly where the codebase stands and where it’s moving — on a real-time dashboard, like this one.

The method doesn’t care how the code got there. A module a founding engineer wrote by hand, a decade ago, and a module an AI assistant generated, last sprint, go through the same standard tooling, get scored against the same quality bar, and show up on the same ledger. Why? Because the stakeholder’s question is never, “who or what wrote this?”, it’s, “can I rely on it?” Vibe coding didn’t create the trust problem this is built to solve. It just made a lot of existing trust problems more urgent, and added some fast-moving new ones of its own.
The picture shows a live trust ledger, six weeks into a remediation engagement. Each module is scored, tiered, and tracked against its own baseline — not folded into a single reassuring average.
That’s a real example of what this looks like in practice — a codebase four modules into a remediation programme. Payments and Auth, the two Tier I modules carrying the highest risk, have climbed from a standing start to 73% and 80% tier-weighted trust respectively. Catalog, Tier II, sits at 74%. Reporting, Tier III and lower priority, has barely moved past 17% — not because it’s been forgotten, but because it hasn’t been engaged with yet, and the dashboard says so plainly, rather than folding it into a flattering overall number.
That honesty is the point. A single trust percentage sitting at 69% doesn’t tell a stakeholder much on its own. A trend line per module, a tiered breakdown of what’s closed versus accepted versus still open, and a plain statement of what would still be outstanding if the engagement stopped today, tells a story a board, a CFO, or a nervous operations director, can actually act on. It sets realistic expectations.
What the tiers actually mean
None of this works if every defect gets treated as equally urgent, which is the fastest way to produce a backlog nobody ever finishes reading — the exact problem this is meant to fix. The tiers exist to keep the work honest about what matters most.
Tier I addresses blast radius: the payment path, the authentication layer, anything that touches customer data or money directly, where a defect left open is a defect the business is actively exposed to.
Tier II is contained, but real — a catalog service that’s wrong in ways that cost time and credibility, but don’t put customers, or revenue, at immediate risk.
Tier III is housekeeping — legitimate work, worth doing, but not the work that determines whether a stakeholder should trust the system this quarter. Grading every module against the same tier definitions, rather than letting each team apply its own sense of what’s urgent, is what makes the resulting score comparable across a codebase — and comparable, later, against itself, over time.
Why clean code is the trustworthy kind
The theory behind this isn’t new or exotic: clean code is the most trustworthy code, and a long history of industry experience bears this out. Code that’s simple, well-tested, consistently structured, and free of known defects is code that behaves predictably — which is, in the end, close to the entire definition of trustworthy software. Complexity, duplication, untested paths, and unpatched vulnerabilities are exactly the things that make software behave unpredictably, and unpredictability is what erodes stakeholder trust faster than almost anything else.
What’s newer is treating trustworthiness as something you measure, rather than something you feel in your senses. Set a baseline first — run the standard toolset against the codebase as it stands today, honestly, without flattering the result — and then do the actual work to move the codebase up that trustworthiness scale, module-by-module, tier-by-tier, with the baseline sitting there as the fixed reference point everything else gets measured against.
Turning AI loose on the problem — with care
This is where AI earns back some of the trust it spent during the vibe-coding phase — not by writing the software, but by interrogating it.
If a lack of development resource was already the bottleneck before any of this started — and for most businesses running lean bespoke software teams, it was — then AI is a genuinely useful way to close that gap without a hiring spree. Point it at the codebase with the same standard quality metrics tools a senior engineer would reach for: static analysis, complexity and maintainability scoring, security and dependency scanning, test coverage measurement. Have it read the codebase the way a thorough, unhurried senior reviewer would, if you could ever find the hours to give one.
This is what AI can be good at. It can follow a repeatable process, more or less mechanically, and produce analysis results, without becoming bored or fatigued. Iterations can be frequent and fast. This is an adjunct to human code review, not a replacement – a way to maintain a data-driven view of how the trustworthiness of the codebase is progressing, as it is being repaired.
The output isn’t a vibe. It’s a structured, reproducible survey of exactly where the codebase stands against known, industry-standard measures — the same measures a skeptical stakeholder, or a technical due-diligence reviewer, would use, had they never heard of AI.
From survey to structured defect log
The next step is to have the AI log whatever problems it finds — properly, as discrete, itemised defects, rather than a wall of prose summarising general impressions. Each one tagged by module, by severity, by the specific risk it represents to the business, rather than only to the code.
This is what turns a one-off audit into something you can actually manage over time. A logged defect can be tiered — the critical, customer-facing, revenue-touching issues in Tier I; the important-but-contained issues in Tier II; the lower-priority housekeeping in Tier III — and tracked to closure, atomically. It can be counted, frozen as a baseline, and referenced every time someone asks “are we actually getting anywhere?” It turns “the codebase needs work” from a gestalt feeling into a reproducible number, with a source.
Fixing what the survey finds
Remediation itself doesn’t have to be AI’s job. The defects that come out of the survey can be fixed the traditional way — an engineer reads the ticket, writes the fix, tests it, moves to the next one — and for plenty of the trickiest, most judgement-heavy defects, that’s still the right approach.
Where AI earns its keep is loop speed. Point AI assistance at the remediation backlog and you get a much tighter fix-and-confirm cycle: propose a fix, write the self-test that would have failed against the original defect and now passes against the fix, and re-run the same quality interrogation immediately to confirm the fix actually moved the needle, rather than just moving the problem somewhere else — without waiting for an engineer’s calendar to free up for every single item. AI can fix the easy issues much faster and more reliably than human coders can.
The self-testing part matters, whichever intelligence is doing the fixing. A fix that isn’t provably tested is just a claim, and the entire point of this exercise is to replace claims with evidence. So, each remediation should come with tests that would have failed against the original defect and now pass against the fix, checked into the codebase, alongside the change, rather than discarded, once the ticket closes — which has the useful side effect of leaving the codebase with better test coverage than it had before, as a by-product of remediation, rather than as a separate line item. Tests that confirm fixes accumulate into an expanded test suite, to prevent future regressions.
Done well, whichever path is doing the fixing, this becomes a loop rather than a one-off pass:
Survey → log → fix → test → re-survey
Run that loop by hand and each pass takes as long as an engineer’s schedule allows. Run it AI-assisted and a pass can take hours — the same fix-and-confirm discipline, just compressed enough to work through a large backlog without every item waiting on scarce senior engineering time. A blended approach is often optimal. Either way, each cycle should narrow the gap between where the codebase is and where the trust ledger says it needs to be, module-by-module.
Done carelessly, AI-assisted remediation can produce exactly the kind of problem vibe coding did in the first place: a codebase that looks better on the surface and is quietly worse underneath. This will be immediately evident, as for each issue addressed, one or more new issues is logged.
The safeguard is the same genuine human quality gate, applied to whatever AI proposes — someone with real engineering judgement reviewing the fix, understanding why it works rather than accepting that it merely passed its own test, and willing to reject a change that technically closes a ticket without actually reducing overall risk. AI taking on the volume of fixes is the leverage. A human holding the gate — whether or not they wrote the fix themselves — is what makes that leverage trustworthy.
Watching the number move
Run that loop consistently and something becomes visible that wasn’t visible before: trust in the codebase measurably increasing. Not a promise that things are getting better — a chart showing it, module-by-module, week-by-week. Tier I items closing faster than they open. The tier-weighted trust score climbing off its baseline. A shrinking list of what would still be outstanding if the engagement stopped today.
That visibility changes the conversation with stakeholders entirely. Instead of a development team asking for continued patience on faith, there’s a number on a dashboard that either moved this week or didn’t — and if it didn’t, that’s visible too, which is its own kind of honesty most software teams have never been in a position to offer.
This is what we offer
We start with a fixed-price diagnostic audit: a baseline reading of your codebase’s trustworthiness across the dimensions that actually matter — security, architecture, delivery governance, performance, and real-world behaviour — using standard, defensible, quality tooling rather than opinion. You get an honest, tiered, itemised number before anyone commits to fixing anything.
From there, remediation is scoped and priced module-by-module, not sold as an open-ended retainer you have to trust blindly. The fixing can be handled the traditional way, by an engineer, or AI-assisted for a tighter fix-and-confirm loop through the backlog — either way, every change passes through a genuine human quality gate before it counts as closed. We track the whole thing on a trust ledger like the one above, so you can watch the number move, in real time, instead of taking anybody’s word for it.
And once a codebase has earned its way up the trust scale, we offer a guardrail retainer to help keep it there — because a codebase that regresses, six months after remediation, hasn’t actually been fixed. It’s been fixed temporarily, and temporarily fixed is precisely the trap that got most businesses into this position in the first place. The continuous re-assessment of the software is what provides the foundation for the trust.
None of this is magic, and we won’t pretend it is. It’s rigour, applied consistently, with AI doing the volume of work no human team was ever going to have the hours for, and a human holding the judgement that AI, on its own, still can’t be trusted with. If your bespoke software has been quietly eroding stakeholder trust for longer than anyone wants to admit — before vibe coding, or because of it — that’s the problem this is built to solve.
Written by Michael Topic. If this describes a codebase you’re responsible for, let’s talk about what a baseline reading would show.

