Nine days. That is how long a security team of five spent clearing four hundred and thirty findings out of a newly installed artificial intelligence code scanner, and by the Thursday afternoon the dashboard finally read zero across every severity band, which felt exactly like winning. Somebody ordered pizza. The work had been real.

Two weeks later that same feature came out of production. It had not been breached and it had not crashed; it had been calculating refund eligibility against the wrong day boundary for roughly eleven thousand accounts, faithfully, every night, precisely as it had been written. Nobody had ever written down which timezone the cutoff used. So it picked one.

Every finding was closed. The software was still wrong, and no amount of refactoring, patching, model upgrading or scanner tuning was ever going to surface it, because the code was a flawless implementation of a requirement that did not exist. That is requirements debt. You cannot refactor it away, and you cannot grep for it either.

What is requirements debt?

Requirements debt is the accumulated cost of intent that was never captured, captured wrong, or never validated, and then implemented correctly. One property separates it from technical debt, and that property is decisive. Technical debt is visible in the artifact: you can open the file, a linter flags it, a profiler measures it, a reviewer can argue with you about whether the shortcut was worth taking, and a refactor removes it without changing what the software does for anybody. Requirements debt is not in the artifact. It sits in the gap between what somebody meant and what anybody wrote down.

So it has no address. A technical debt item can be given a ticket, an estimate and a place in a sprint; requirements debt cannot, because the thing you would file the ticket against is the absence of a sentence nobody has noticed is absent. Interest accrues anyway. It compounds through every artifact built downstream of the gap, so the design inherits it, the test suite inherits it, and the acceptance criteria confirm it, all of them agreeing with each other and all of them wrong in the same direction. Nothing disagrees. That agreement is what makes it expensive.

I used to call this a documentation problem. Twenty-five years in enterprise software delivery has moved me off that position fairly firmly. Documentation is what you produce after the thinking has already happened, and a team can produce four hundred immaculate pages while carrying more requirements debt than a team that produced nine bullet points and then argued about them for two hours in a room in Boucherville with the whiteboard markers running dry. Volume is not validation. The debt lives in the questions nobody asked.

Why is AI security debt the symptom and not the disease?

Because a vulnerability has a shape and a missing requirement does not. Ask a security leader what worries them this year and the answer is consistent, and it now has survey weight behind it.

#1 · 100%
Artificial-intelligence-generated code is the number-one blindspot for application security and product security teams, and 100% of organizations expect an increased 2026 budget for AI security related initiatives, in a survey of 400 chief information security officers and security leaders.
Source: Cycode, "State of Product Security for the AI Era 2026". Industry: enterprise application and product security.

That budget is answering something real. Generative models do produce insecure patterns, do leak credentials into commits, and do ship both faster than review can absorb them; I made that case at length in the piece on AI security debt. None of it is wrong. It is downstream.

Here is the mechanism. A vulnerability is a defect in how the code does a thing, and every scanner on the market works because the wrong thing has a recognisable form: an unparameterized query, a hardcoded credential, an unchecked bound, a dependency carrying a published advisory. Requirements debt has no form to recognise. The refund feature at the top of this article passed the entire pipeline on the first run with zero findings, and it should have, because no ruleset anywhere contains a rule that reads "this function silently assumes Eastern time." Correct code. Wrong software.

So the money follows the findings, and the findings follow the shapes. That is not stupidity. It is measurability doing what measurability always does, which is to make the countable problem look like the important one, and it is the oldest budget allocation failure in this industry wearing a new outfit.

Can you refactor your way out of a bad requirement?

No. The reason is structural rather than a matter of effort or skill. Refactoring has a definition, and the one everybody uses is Martin Fowler's: changing the internal structure of software without changing its observable behaviour. Read that against a bad requirement, twice. Observable behaviour is precisely what the wrong requirement got wrong, so a faithful refactor preserves the defect by design and hands you back a cleaner, better named, better tested version of the same wrong thing.

Patch the vulnerability and the behaviour stays. Rewrite the module in a safer language and the behaviour stays. Point an agent at the repository, ask it to modernise, and the behaviour arrives faster, with docstrings. There is now benchmark evidence for what happens when the instruction itself is unclear.

7.22 points
Average drop in Pass@1 accuracy across every large language model evaluated when the same coding task was stated with ambiguous rather than clear requirements, on Orchid, a benchmark of 1,304 function-level tasks covering lexical, syntactic, semantic and vagueness ambiguity. The largest single decline measured was 31.10 points, and the models did not ask for clarification; they produced functionally divergent implementations instead.

Two words in that result matter more than the numbers do: functionally divergent. Handed the same unclear requirement, the model does not stall and it does not ask. It commits. It picks one interpretation and writes clean, plausible, well structured code around it, and the next model along picks a different interpretation and does exactly the same thing, and both outputs survive review because both are internally coherent. Ambiguity in, confidence out. That is the accelerant.

Where does requirements debt actually accrue?

Four places, and not one of them is the codebase.

Where requirements debt accrues FIRST COMMIT The unasked question timezones, rounding, who counts as an active user The corridor decision settled in 90 seconds, never written down The assumed default chosen by a library, not by a person True in March, not in June the regulation moved, the specification did not REPOSITORY linters, scanners, tests, agents, code review all report clean Nothing to the right of that line can see a requirement that was never written.
Requirements debt accrues before the first commit, in four places no repository scan can reach.

The unasked question. Somebody in the building knows the answer and nobody queries them, usually because the question sounds too basic to ask out loud in front of a room. Timezones. Rounding rules. Who counts as an active user, exactly, on the day the contract renews.

The decision made in a corridor. Two people settle a genuine ambiguity in ninety seconds outside a meeting room, correctly, and the resolution never reaches text. Half a year later neither of them remembers deciding it, the code is the only surviving record of the choice, and nobody left in the room can explain to an auditor why the software behaves the way it does.

The assumed default. Nobody chose Eastern time. The absence of a stated timezone got resolved silently, by a library, at a layer nobody was watching, and the assumption became a requirement the moment it shipped and somebody started depending on it.

The requirement that was true in March. Regulation moves, pricing moves, the partner integration moves. The specification does not move, because nothing in the system knows the world did.

Notice the common property. Every one of these is a fact about people, timing or context rather than a fact about code, which is exactly why the tooling bolted onto your coding stack cannot see any of it; I walked through what that stack does and does not cover in the hidden cost your AI coding stack ignores. The repository is the wrong place to look. Nothing there is missing.

Between December 21 and December 31, 2022, Southwest Airlines cancelled close to 17,000 flights. A winter storm was the trigger, but the storm hit every carrier in North America and only one carrier came apart. What gave way was the crew scheduling system.

That software was not defective in the way the word is normally used. It had run for years, it had been maintained and patched, and it did precisely what it had been built to do. What it had never been asked to do was rebuild crew pairings at the volume the storm produced, all at once, across an entire point-to-point network. That scenario had never been written down as a requirement.

Chief operating officer Andrew Watterson testified before the United States Senate Commerce, Science and Transportation Committee on February 9, 2023, and his account was that the disruption revealed a need to add functionality to the crew scheduling software so it could work through a large backlog of broken crew pairings. The upgrade went into production the following day. Southwest has invested heavily in that system since.

Look at what the fix actually was. Not a refactor. Not a patch to broken logic. New behaviour, specified for a case that had never been specified, which was the only thing that could have worked. Cheap to ask in a planning session. Expensive to learn at an airport.

Source: Written testimony of Andrew Watterson, Chief Operating Officer, Southwest Airlines, United States Senate Committee on Commerce, Science, and Transportation, "Strengthening Airline Operations and Consumer Protections," February 9, 2023. Vendor subject: Southwest describing its own incident, which is the correct primary source for the mechanism.

How do you pay down requirements debt before code?

You cannot pay it down afterwards, so the entire answer sits upstream of the first commit. Three moves, ordered by what they return.

Make absence a first-class output. Every review your organization runs asks whether what is written is correct. Almost none of them asks what is not written, because there is no artifact to review and no obvious owner to assign it to. Change the question. A discovery pass whose deliverable is a list of open questions, stated assumptions and unresolved conflicts produces something no technical review ever will, and it is the only artifact in the whole chain that describes the gap instead of the content.

Write down the corridor decisions the same day. Two sentences and a date. I have watched more expensive rework trace back to an unrecorded five-minute agreement between two competent people than to any coding mistake I can name, and the fix costs less than the meeting that produced it.

Interrogate the specification from more than one angle. A single reviewer confirms their own reading of a paragraph, which is not a character flaw, it is simply how reading works. A security perspective, a data perspective, a compliance perspective and a delivery perspective looking at that same paragraph will disagree with each other, and the disagreement is the product. This is the argument I have been making since vibe coding died and the specs stayed broken, and generative tooling has only sharpened it.

One caveat, because none of this is free. Discovery has a real cost and it is entirely possible to overspend on it; a team can interview itself into paralysis and call the result rigour. The test I use is narrow. Ask whether the answer to the question could change what gets built. If it could not, stop asking it.

Technical debt is a defect in how the code works. Requirements debt is a defect in what the code was told to do.

Technical debt and AI security debt are both visible in the artifact, which is why they get tickets, budgets and dashboards. Requirements debt is the intent that was never captured, captured wrong, or never validated, and it is invisible precisely because the code implements it faithfully. Refactoring preserves observable behaviour by definition, so it cannot remove a defect that lives in the behaviour itself.

Generative tooling does not create requirements debt. It accelerates it, because an ambiguous requirement produces confident, clean, divergent implementations instead of a stall and a question. The only place to pay it down is upstream, before there is code to argue with.

What are the most common questions about requirements debt?

Requirements debt is the accumulated cost of intent that was never captured, captured wrong, or never validated, and then implemented correctly by the software. It differs from technical debt because it is not visible in the code. The implementation is faithful, so linters, scanners, tests and reviews all report that nothing is wrong.
Technical debt is a defect in how the code works, and it lives in the artifact, which is why a linter can flag it and a refactor can remove it without changing what the software does for anybody. Requirements debt is a defect in what the code was told to do. It lives in the gap between what somebody meant and what anybody wrote down, so no tool can point at it and no refactor can remove it.
No. Refactoring is defined as changing the internal structure of software without changing its observable behaviour. When a requirement is wrong or missing, the observable behaviour is the defect, so a refactor preserves it by design and hands back a cleaner, better tested version of the same wrong result.
It does not create it, it accelerates it. On Orchid, a 2026 benchmark of 1,304 function-level tasks, ambiguous requirements reduced Pass@1 accuracy by an average of 7.22 percentage points across every model evaluated, with a largest single decline of 31.10 points, and the models did not ask for clarification. They produced functionally divergent implementations instead, which means an unclear requirement now yields fast, confident, plausible code rather than a stall and a question.
AI security debt is real, and it is downstream. A vulnerability has a recognisable form, such as an unparameterized query or a hardcoded credential, which is exactly why scanners find it and budgets follow it. A missing requirement has no form to recognise, so it passes every scanner cleanly, satisfies every test that was written from the same gap, and ships.
Upstream, before there is any code to argue with. Make absence a deliverable by running a discovery pass whose output is open questions, stated assumptions and unresolved conflicts; record corridor decisions the same day in two sentences and a date; and review the specification from several expert perspectives at once, because the disagreement between those perspectives is what surfaces the gap.
Nicolas Payette, CEO and Founder of Specira AI
CEO and Founder, Specira AI

Nicolas Payette has spent 25 years in enterprise software delivery, leading digital transformations at companies like Technology Evaluation Centers and Optimal Solutions. He founded Specira AI to solve the root cause of project failure: unclear requirements, not slow code.