Phase 3: Can our software factory catch vague instructions before building?
Building on Phase 2's durable crash-recovery foundation, Phase 3 tackles the riskiest unsolved problem in the whole project: a written instruction ("spec") that looks complete but secretly leaves an important decision unstated. A human engineer would notice and ask a question in the hallway. Our automated factory has no hallway so until now, it would just guess, silently, and build whatever it happened to assume. We built a mechanical ambiguity detector that reads each instruction three times through three different personalities and flags exactly the points where those three readings disagree before a single dollar is spent building. We proved it on two real instructions for the same feature: it correctly stopped the vague one (naming the three specific unanswered questions) and correctly passed the clear one. Along the way our first version was too trigger-happy and flagged a perfectly clear instruction as vague; we caught that, fixed it, and locked the fix in place. We then completed the phase: turning that detection into a back-and-forth conversation that refines an instruction until it's clear (T3.2), letting acceptance tests be compiled directly from the spec instead of hand-translated by an AI (T3.3), and grading the factory's own bug-catching critic against planted defects (T3.4). Verdict: the two research-risk blockers of Phase 3 are retired, and the phase is complete.
What we set out to solve
The factory runs on written instructions. Someone describes what they want, and the robot builds it. The whole system's safety depends on those instructions being clear but in the real world they almost never are.
Here's the trap. An instruction like "apply a percentage discount to a list of order items" reads perfectly well. But it quietly fails to say: what happens if the list is empty? What if the discount is negative or over 100%? What if an item is missing its price? A human would spot these gaps and ask. Our robot can't ask anyone so it silently picks an answer, and nobody finds out which answer until the wrong behavior has already been built, tested (against the robot's own wrong assumption), and shipped.
This is the single hardest problem in this phase because there's no off-the-shelf solution detecting "this instruction is secretly ambiguous" is genuinely unsolved, research-grade work. So it went first: if we couldn't make it work, we needed to know early.
How we tested it (in real-world terms)
The core idea borrows a trick from safety-critical engineering called "N-version" checking: if you want to know whether an instruction is ambiguous, don't ask one reader ask several independent readers and see if they disagree. (This is an application of the test oracle concept: multiple independent interpretations of the same spec act as oracles for each other.) Disagreement between careful readers is the ambiguity, made visible.
We have the same AI read each instruction three times, wearing a different hat each time:
- a literal reader, who answers only what the instruction actually says and flatly reports "not specified" for anything it doesn't;
- an adversarial reviewer, who looks for the most damaging way a careless builder might interpret it;
- an implementer, who just picks the most conventional default and moves on.
Each reader answers the same fixed checklist of danger-zone questions (empty input, oversized input, invalid input, duplicates, missing fields, downstream failures). Then a completely mechanical, no-AI comparison step checks whether the three readers landed on genuinely different behaviors. If they did, the instruction is bounced back with the specific disagreement attached not a vague "this is unclear," but "on empty input, one reading says return nothing, another says leave it unchanged, a third says apply the discount anyway which is correct?"
What we learned along the way
The uncomfortable discovery: our first working version was too suspicious. When we tried it on a deliberately clear instruction, it flagged that one as ambiguous too five false alarms. Looking closely, the "disagreements" weren't real: the three readers actually agreed, they'd just used different words ("returns an empty list" vs. "empty items give an empty list"). Our comparison step was mistaking a difference in wording for a difference in meaning.
This matters more than it might sound. A safety alarm that goes off for everything including the things that are fine is worse than useless, because people quickly learn to ignore it. This is a classic Goodhart dynamic: a metric that was meant to measure safety stops measuring anything useful once it triggers on everything. A detector that stops every instruction isn't protecting anyone; it's just noise. So getting the precision right wasn't polish it was the difference between a real safeguard and one that would be switched off within a week out of frustration.
We fixed it by teaching the comparison step two things: that "no opinion" isn't the same as "a conflicting opinion," and that differently-worded descriptions of the same behavior should be treated as agreement, while genuinely different behaviors (say, two different kinds of error) stay flagged.
What we resolved
With the fix in place, we re-ran the real test:
| The instruction | What it left unsaid | Outcome |
|---|---|---|
| Deliberately vague discount feature | empty input, invalid input, oversized input | ✅ Stopped named all 3 gaps |
| Clear version (same feature, gaps filled in) | nothing | ✅ Passed cleanly |
- It caught the real ambiguity. The vague instruction was halted before any build spend, with the three specific unanswered questions handed back for a human to resolve.
- It didn't cry wolf. The clear instruction sailed through with zero false alarms, even though its three readings were worded differently.
- It's cheap. Reading an instruction three times costs about a quarter, and it happens before the expensive building step so it saves money by preventing wasted builds, not adding to them.
How we proved we actually resolved it
The proof is the same discipline we used in Phase 1: a safeguard you can't demonstrate catching a real problem is just decoration.
- We wrote a genuinely ambiguous instruction on purpose and confirmed the detector stops it and names the exact gaps, rather than a vague complaint.
- We wrote a genuinely clear version of the same feature and confirmed the detector lets it through proving it isn't just blocking everything.
- Most important: we saved the three real AI readings from that live test and turned them into a permanent, automatic check. If anyone ever changes the comparison logic in a way that would bring back the false alarms or let the real ambiguity slip through that check fails immediately. The exact scenario that caught us out can never quietly come back.
That third step is what makes this trustworthy rather than a one-time demo. The detector has teeth, and it's precise, and both of those properties are now guarded against regression.
The rest of Phase 3 (now also done)
The ambiguity detector answered the hardest question. Three further pieces built on it complete the phase:
- We turned detection into a conversation (T3.2). The factory no longer just stops on an ambiguous instruction it asks you the specific questions the readers disagreed on, folds your answers back into the document, and re-checks, until the instruction is clear. Crucially, the refined document not the chat is what drives the build, and the loop never quietly gives up: if the ambiguity isn't resolved, it says so plainly rather than proceeding.
- We made the acceptance tests as precise as the instructions (T3.3). Until now, "the software should do X" was written in prose and a coding AI wrote the test for it an unchecked translation step. Now acceptance criteria can be written in a small structured form that the factory itself compiles directly into runnable checks, with no AI in between. We proved those checks have teeth: they pass correct code and fail wrong code.
- We graded the grader (T3.4). The factory has an automated critic whose job is to attack a change and try to break it. We now measure how good that critic actually is by planting known bugs in working code and counting how many it catches and how often it cries wolf on clean code. This is the oracle-strength floor concept applied to the critic itself: critic quality became a tracked number that has to earn its way up through the same statistical bar as every other part of the factory.
The ambiguity detector runs as an opt-in so it doesn't add cost to routine demo runs; the acceptance-criteria compiler and critic calibration are always-on building blocks the factory can call.
Bottom line for a decision-maker
- Phase 3 is complete. All four pieces are built, tested, and merged; the two research-risk blockers silently ambiguous instructions and weak test oracles are retired.
- The research risk is gone. The one problem with no known solution detecting secretly-ambiguous instructions before they waste money now has a working, proven detector, and a conversation to resolve what it finds.
- The oracles got stronger. Acceptance tests can now be compiled straight from the spec instead of hand-translated by an AI, and the factory's own bug-catching critic is measured, not assumed.
- It's precise, not just sensitive. We found and fixed our own "cries wolf" problem, and precision is now scored throughout safeguards people will keep switched on.
- The plan holds; next is Phase 4 execution safety hardening (sandboxing, credential scoping, real budget enforcement), which is well-understood engineering rather than research risk.
Ready to put these ideas into practice?
Book a free 30-minute consultation to discuss how AI-driven delivery engineering can transform your organisation.
Book a Strategy Call