Inquiry into Spec-driven development
With Gemini
Given the current hype on Spec-driven development, I'd like to chat about its occurrence through software history. What is the earliest known example of Spec-driven software development?
Strictly speaking, the first industrial-scale precursor is SAGE (Semi-Automatic Ground Environment) in the 1950s—a massive Cold War air defense system built by IBM and MIT Lincoln Laboratory where requirements and specifications had to be strictly separated from coding simply because hundreds of programmers couldn't coordinate otherwise.
However, the moment "spec-driven development" entered the collective vocabulary as a recognized discipline was the 1968 NATO Software Engineering Conference in Garmisch, Germany. Attendees were panicked over the "software crisis" — hardware was advancing rapidly, but writing large software was dangerously ad-hoc. Their core solution was to borrow the blueprint model from civil and mechanical engineering: writing exhaustive functional specifications before a line of code was written, attempting to turn software creation into a predictable manufacturing pipeline.
1950s. They wouldn't have had even basic automated compilers at that point. Intent in flowcharts or English would have had to been translated by people writing the machine code? At this point it is very much about division of labor?
And what was this "software crisis"?
You hit the nail on the head regarding the technological reality. In the 1950s—long before high-level compilers were mainstream—programmers were wrestling with raw assembly or machine code on massive vacuum-tube hardware like the AN/FSQ-7 for SAGE.
Because code was so agonizingly low-level and error-prone, the human pipeline had to be strictly stratified. System architects and analysts drafted exhaustive logic flowcharts and English specifications. Then, human coders translated those blueprints into punch cards and assembly instructions. At that scale, spec-driven development wasn't about mathematical purity; it was a desperate exercise in industrial division of labor. You couldn't have hundreds of people writing code without a rigid contract of what they were supposed to be building, or the whole project would implode under its own weight.
As for the "software crisis," it was the collective panic that crystallized around that exact industrial bottleneck. Coined formally at this NATO conference, the crisis was the realization that while hardware was scaling rapidly, our ability to build reliable software was linear at best—and often completely stagnant. Projects were chronically late, wildly over budget, and prone to catastrophic failures.
The industry looked at civil engineering—bridges, skyscrapers, manufacturing assembly lines—and thought, "We need blueprints. We need specs. If we can just formalize the requirements before a single line of code is written, we can manufacture software like cars." Of course, unlike physical buildings, software is fundamentally malleable, which is why that industrial dream immediately ran into a wall.
Gotcha, that makes some sense - borrow from a developed field. Even though you say this strategy went nowhere, I did read the report from the 1968 NATO conference, and found this quote:
Kolence: (from On the interaction between software design techniques and software management problems’)
»At the abstract level, a concise mathematical notation is required by which to express the essential structures
and relationships irrespective of the particular software product being implemented. For example, in the area of
computer central processor design, the notation that satisfies this requirement is Boolean Algebra. The notation
of Ken Iverson is an attempt to provide an equivalent notation for software.«
What notation of Iverson is meant? Did this go anywhere?
That notation is APL (A Programming Language), which Kenneth Iverson developed in the early 1960s while at Harvard and later refined at IBM.
Iverson’s breakthrough was creating a unified, highly concise mathematical notation that treated entire arrays and matrices as first-class citizens, allowing complex algorithms to be expressed in a single line without traditional procedural control loops (
fororwhile).Did it go anywhere? Yes and no, in a fascinating way:
As a universal software spec: It didn't become the meta-specification language for all of software engineering as Kolence and other early purists hoped. Mainstream enterprise software went down the path of verbose procedural languages (COBOL, PL/I, and later C and Java).
As an actual programming language: APL escaped the academic drawing board and became a commercial powerhouse in fields requiring heavy mathematical and matrix computation—particularly Wall Street, financial forecasting, insurance, and logistics.
However, APL earned a legendary reputation as a "write-only" language. Because it relied on a custom keyboard layout of esoteric mathematical symbols (
⍥,⍴,⍳,∇), a 5-line APL program could do the work of 200 lines of Java, but trying to read someone else's APL code six months later felt like decoding ancient hieroglyphics. It proved that while concise notation is powerful, human readability and shared mental models remain the ultimate bottleneck.
Well, clearly APL itself didn't survive until now - although I know it influenced
some very popular libraries: numpy and pytorch.
Where did the spec-driven development history go next? At some point logic programming was invented - which it could be argued is also a spec.
Spot on regarding APL's legacy—those array-oriented primitives and vectorized thinking survived and heavily inspired modern computational libraries like
numpyandpytorch.As for where the epistemic, specification-driven lineage went next: it veered straight into Logic Programming in the 1970s (anchored by languages like Prolog, developed by Alain Colmerauer and Robert Kowalski).
Your intuition that logic programming is essentially "executable specification" is dead on. In Prolog, you don’t write step-by-step algorithms. Instead, you declare facts and rules (using Horn clauses), and an automated inference engine runs a resolution theorem-prover to answer queries. You literally write the logical specification of the domain, and the machine computes the execution path.
Like the formal methods before it, logic programming promised to bridge the gap between human intent and machine execution without the "noise" of imperative boilerplate. But it hit a brick wall when scaled to massive, real-world systems:
The Control Flow Black Box: When a logic program grew large, predicting how the inference engine evaluated rules became notoriously difficult. Small tweaks to rule ordering could cause exponential explosions in execution time or send the solver into infinite loops.
State and Side Effects: Logic programming excelled at discrete, rule-based domains (like natural language parsing or expert systems), but wrestling with asynchronous I/O, user interfaces, and mutable application state felt like hammering a square peg into a round hole.
While general-purpose logic programming didn't conquer mainstream enterprise software, its DNA survived in places like database query optimizers, static analysis tools, security authorization engines, and modern constraint solvers.
From there, the industry realized that pure mathematical and logical specs were too heavy for everyday business apps, prompting the great industrial pivot: trying to draw the specs instead of writing them, leading straight into the UML and Model-Driven Architecture era.
I believe there was also a problem with logic programming theorem-provers and multi-threading? If memory serves, Japan invested heavily into logic programming.
Ah yes, the Unified Modeling Language - the universal graphical model for OOP. Only it didn't quite work out that way. It seems specifying function internals (effectively pseudo-code) is quite difficult in UML, possibly taking longer than doing the same in Java.
I mostly know UML as an software architecture language, that nobody remembers the exact details of the different arrow types of. How did it go from a "4GL" (graphical) programming language to what I know today?
Your memory serves you right. Japan’s Ministry of International Trade and Industry (MITI) launched the massive Fifth Generation Computer Systems (FGCS) project in 1982, pumping hundreds of millions of dollars into parallel logic programming and hardware designed to run Prolog natively at massive scale.
The project hit a wall precisely because of the concurrency challenge. While concurrent logic programming languages (like Guarded Horn Clauses) were mathematically elegant, orchestrating fine-grained parallelism and shared mutable state across early multi-processor hardware proved vastly more difficult than anticipated. Meanwhile, commodity hardware powered by RISC architecture, C++, and relational databases exploded in performance, completely blindsiding the symbolic AI and logic programming bets.
As for UML, your diagnosis of why the "Graphical 4GL" dream died is spot on.
In the late 1990s, when Grady Booch, James Rumbaugh, and Ivar Jacobson unified their notations into UML under the Rational Software banner, the pitch wasn't just sketching — it was Model-Driven Architecture (MDA) and "executable UML" (xUML). The grand vision was that software engineers would become "system modelers," drawing comprehensive class diagrams, sequence diagrams, and detailed state machines. An automated code generator would then spit out the complete C++ or Java application, and you'd never have to write low-level code again.
It crashed against reality for a few brutal reasons:
The Granularity Trap: Trying to draw the algorithmic logic of a loop, a conditional branch, or a complex data transformation using boxes, lines, and activity diagrams is like trying to paint the Mona Lisa with a roller brush. Text is fundamentally better suited for expression logic than two-dimensional shapes.
The Round-Trip Engineering Nightmare: Tools promised that you could change the code and the diagram would update automatically, or vice versa. In practice, the synchronization algorithms were brittle, and the generated codebases were bloated with framework boilerplate.
The Drift: The moment a developer made a quick hotfix in the code text editor at 2:00 AM, the graphical model was instantly invalidated. Keeping documentation and code in sync manually proved to be an administrative tax nobody wanted to pay.
That is how UML survived only as a ghost of its former self. It degenerated from an executable programming language into a whiteboard sketch language—useful for a high-level architectural discussion over coffee, but largely abandoned as a source of truth, leaving behind a legacy of arguments over whether a hollow or solid diamond represented aggregation versus composition.
And then BDD was invented at some point, with good intentions of the three amigos meeting, but subsequent tools devolved it into "anyone can write executable specs"?
Which, as it turns out - isn't actually that easy, at least not unambiguous specs.
That is precisely where the wheels came off.
Behavior-Driven Development (BDD), pioneered by Dan North in the mid-2000s as an evolution of Test-Driven Development, had a noble and genuinely revolutionary premise: bridging the communication gap between business stakeholders, QA, and developers—the so-called "Three Amigos." The goal was requirements discovery, using structured conversations to ensure everyone agreed on what the system actually needed to do before writing code.
The fatal error came when tools like Cucumber, SpecFlow, and the
Given/When/ThenGherkin syntax tried to turn those conversational artifacts into executable code.The marketing pitch claimed that because the specs were written in plain English, "anyone" could write them. But that premise ignores a fundamental linguistic reality: Human natural language is inherently ambiguous, context-dependent, and fluid. Code execution requires absolute determinism.
When non-technical stakeholders actually tried to write Gherkin specs, it didn't empower them; it just forced them to write clumsy, rigid pseudocode. And when developers tried to keep up, they ended up building massive, brittle layers of regex "glue code" to map sentences like “Given a user logs in” to underlying backend API calls.
Instead of fostering better human conversations, BDD devolved into an administrative compliance ritual. The executable specs didn't clarify requirements — they became a secondary, highly fragile codebase that everyone grew to resent maintaining.
And finally, we're back in 2026 - when Spec-driven development is back in vogue but with AI agents as the target of the division of labor. Which is where SAGE started us on this journey.
Will this go down the same route again? Who knows. My only advice is this: If you try out spec-driven development (with or without AI-agents) and find it lacking, know that many have tried their hand at this same problem. Maybe take a look into history before the hype consumes you.
Programs kept crashing
A holy spec was written
The world did not care