Posted in

The Specification Is the Source of Truth: An Introduction to SDAIS

Print Factory

A paradigm shift in software development — where humans write requirements and AI agents synthesise everything else.


Software development has always had a coordination problem. Not the coordination between developers, though that is hard enough. The coordination problem I mean is the one between intent and artefact — between what a system is supposed to do and what it actually does. Requirements Engineering tries note the intend in

In the beginning of a project, the gap is small. Requirements are fresh, developers remember the design discussions, and the code more or less matches the specification. Then time passes. Priorities shift. A developer leaves and takes institutional knowledge with them. A framework upgrade changes how something works at the boundary. A deadline forces a shortcut that becomes permanent. The specification — if it existed at all — stops being updated because everyone is too busy keeping the system running.

A year later, the only reliable source of truth is the code itself. But reading the code to understand intent means reverse-engineering decisions made in contexts no one remembers. Every refactoring carries risk. Every migration is expensive. The chain from what we need to what we built has broken, and nobody is quite sure where.

This is not an unusual situation. It is the normal trajectory of software under continuous change.

Specification-Driven AI Synthesis (SDAIS) is a paradigm built around a single structural answer to this problem: the specification can never fall behind the code if the code is always derived from the specification. Not periodically reconciled with it. Not summarised from it. Derived — by AI agents, every time.


The Inversion

Traditional AI-assisted development treats the language model as a capable tool inside a human workflow. The human remains the code author. AI helps with specific tasks — filling in a function body, explaining an unfamiliar library, generating test cases. This is genuinely useful, but it leaves the fundamental problem untouched: human developers still write and own the implementation, which means the specification-to-code chain still breaks whenever human attention moves elsewhere.

SDAIS inverts the relationship entirely.

The Inversion

In traditional development the human owns the code and AI assists. In SDAIS the human owns the specification and AI synthesises everything else.

In SDAIS, humans author requirements exclusively. AI agents synthesise, review, and refine all implementation code. No human writes implementation code. The human role is that of architect and specifier; the AI role is that of implementer, reviewer, and annotator.

This inversion has a structural consequence that is easy to state but profound to sit with: the specification can never fall behind the code, because the code is always derived from it. When requirements change, you update the specification. Code follows. The chain from intent to artefact is enforced by the process itself.


Three Load-Bearing Words

The name Specification-Driven AI Synthesis is not marketing. Each word carries weight.

Specification-Driven — a structured, versioned requirements document is the single upstream artefact and the authoritative source of truth. All AI activity is derived from and traceable to it. The document is called the Requirements Specification File (RSF) and it consists of individual Markdown files, one per requirement, versioned in git.

AI — one or more AI agents execute the full development lifecycle: generation, annotation, review, refinement, and test authoring. These agents are not interchangeable; different phases require different cognitive strengths, and SDAIS assigns specialist roles accordingly.

Synthesis — the output is not a translation of human code, but a synthesis from requirements. The AI selects data structures, idioms, and implementation strategy within the constraints the specifier has provided. This means the programming language can itself be a constraint stated in the specification rather than a presumption.


The Specification: Five Types, One Source of Truth

Everything in SDAIS flows from the RSF. Before a single line of code is generated, the RSF must be authored and validated. It consists of five item types, each a single Markdown file with a structured format.

RSF Item Types

The five RSF item types. Every item is a single Markdown file. Together they form the upstream artefact from which all code is derived.

Functional Requirements (FR) describe what the system must do — observable behaviours, not implementation details. Every FR must have at least one corresponding Acceptance Criterion.

Non-Functional Requirements (NFR) describe quality attributes: performance, reliability, scalability. A critical rule applies here — NFRs without a numeric bound are invalid. “The system must be fast” is not an NFR. “The system must respond to 95% of requests within 200 ms under a load of 1,000 concurrent connections” is. The SemanticAuditor agent enforces this automatically, flagging any UNQUANTIFIED requirement before code generation begins.

Constraints (C) narrow the solution space without describing a feature: the implementation language, forbidden third-party libraries, mandatory design patterns. A constraint item can even activate a different generation mode — adding one that reads Generation mode: TDD switches the entire workflow to a test-first approach.

Environment items (E) capture deployment and runtime facts the AI must know: database connections, infrastructure assumptions, operating system targets. These are not generated; they are verified. A dedicated Grounder agent confirms that every E-item describes something that actually exists in the target infrastructure, opening a finding for each element it cannot confirm.

Acceptance Criteria (AC) define programmatically verifiable conditions that confirm FRs are satisfied. They specify inputs, expected outputs, and observable side effects. An AC that cannot be verified programmatically is flagged UNTESTABLE by the audit step. Every FR must be covered by at least one AC, and the Reviewer agent checks this during every review pass.

Each item lives in its own file under sdais/rsf/v<N>/, where N is the RSF version number. When requirements change, a new version directory is created. Old versions are never modified — they remain as the permanent record of what was specified at each point in time. This is the version history that git stores for code applied to requirements instead.


Implicit Knowledge Must Become Explicit

Here is one of the harder consequences of the SDAIS inversion: when a human developer writes code, they embed enormous amounts of implicit knowledge. Naming choices encode intent. A guard clause encodes an assumption about input validity. A particular data structure encodes a performance expectation. None of this is written down. It lives in the developer’s head and, if you are lucky, loosely in comments.

In SDAIS, that knowledge must be stated in the specification or it does not exist. This raises the quality bar for requirements considerably. It is also, eventually, what makes the system more maintainable: a codebase derived from a complete, explicit specification is a codebase whose every decision is traceable to a stated requirement.

This is a discipline. Writing precise, testable, quantified requirements is harder than writing approximate ones. The SemanticAuditor exists precisely to enforce this — it runs before any code is generated and flags requirements that are AMBIGUOUS, INCOMPLETE, CONTRADICTORY, INFEASIBLE, UNTESTABLE, or UNQUANTIFIED. The human resolves findings, the RSF version increments, and the audit reruns. Only when the RSF is Cleared — all findings Resolved or Waived — does code generation begin.

The Requirements Audit Report (RAR) is the document set that records these findings. Each finding is its own file, referencing the RSF item it concerns, and it remains permanently as the audit trail even after the underlying requirement has been fixed. When you look at a mature SDAIS project’s git history, you can see not just how the code evolved but why the requirements evolved — which findings were raised, which items were amended, which decisions were consciously waived.


A Team of Specialists

The second structural insight of SDAIS is that different phases of development require different cognitive strengths. A single “do everything” model is not the right tool for every step. The paradigm defines ten specialist agent roles, each with a recommended capability tier.

Agent Roles

SDAIS assigns ten specialist agent roles across four phases. Each role has a recommended capability tier, because different phases reward different cognitive strengths.

The SemanticAuditor, for example, needs to detect subtle contradictions in natural language — “the system must always respond within 200 ms” next to “the system must retry failed upstream calls up to five times with exponential backoff” is a potential conflict that requires careful reasoning to surface. A model strong in logical inference does this well.

The Generator, by contrast, needs to produce correct, idiomatic code at scale. It reads a set of requirements and synthesises a complete implementation. The cognitive task is different — less about finding hidden contradictions and more about producing structurally sound, well-annotated code. High-coding models excel here.

The Reviewer sits at the intersection: it reads code and its annotations, cross-references them against the RSF, and produces precise, actionable findings. It can be either tier, depending on the complexity of the codebase and requirements. What matters is consistency — the same model should review all rounds of a given project so that findings are interpreted with the same baseline.

This is not premature optimisation. Assigning the right model to each role is what makes the review loop converge reliably rather than producing inconsistent finding quality from round to round.

An optional Architecture Definition File (ADF) produced by the Designer agent bridges specification and implementation. Before any code is generated, the Designer reads all cleared RSF items and produces a module decomposition, API surface definitions, data flows, and design decisions — each traceable to one or more RSF item IDs. The human reviews and approves the ADF before code generation begins. The Generator then reads it as structural context. RSF items remain authoritative if ADF and RSF conflict, but the ADF guides the shape of the implementation in ways that would otherwise be left entirely to the AI’s discretion.


The Annotation Block: How Agents Remember

There is a fundamental problem with stateless AI agents in multi-round development. A Reviewer running in round 3 of a review cycle has no memory of what the Generator intended in round 1. Without some form of persistent intent encoding, every review pass would require re-reading the entire RSF from scratch and re-deriving each unit’s purpose from context.

SDAIS solves this with [ANN] blocks: structured comment blocks embedded directly in the generated source code, written in the comment syntax of whatever language is being used.

Annotation Block

An [ANN] block evolves through rounds. The Generator creates it; the Reviewer appends findings; the Refiner resolves them and sets (VERIFIED) true.

Every [ANN] block contains structured labels — all written in the comment syntax of the target language:

  • (ANN-ID) — a stable unique identifier (ANN-7f3a9c2e) generated once at creation and never changed. This is how agents and humans refer to a specific unit across all subsequent rounds.
  • (ORIGIN) — the RSF item IDs this unit implements. A unit that implements FR-0003 and satisfies NFR-0001 records both.
  • (TASK) — a declarative statement of what the unit does, separate from the code itself.
  • (PRE) / (POST) — preconditions and postconditions, derived directly from Design-by-Contract principles.
  • (AGENT) / (VERIFIED) / (ROUND) — the traceability labels that record who last touched this block, whether it passed review, and in which round.

When the Reviewer finds a violation, it appends (FINDING:n), (SEVERITY:n), and (HINT:n) labels directly to the block — co-indexed so each finding, its severity, and its resolution instruction form a coherent set. The Refiner reads these hints, fixes the implementation, and appends (FINDING:n:STATUS) recording what was done. When all findings in a block are resolved, (VERIFIED) becomes true.

This labelling system is the inter-agent protocol. It is not documentation in the traditional sense — it is the mechanism by which a stateless Reviewer in round 4 can understand what a Generator intended in round 0, what a Reviewer found in round 2, and what a Refiner fixed in round 3. The block carries its own history.

The (DEPENDS-ON) label deserves special mention. When the Reviewer discovers that a unit is broken, it does not only flag that unit — it runs a dependency cascade check, finding every other unit whose (DEPENDS-ON) references the broken unit and appending a cascade finding to each. This prevents errors from silently propagating through the call graph between review rounds.


The Refinement Loop: Quality as an Emergent Property

No AI agent produces perfect output on the first pass. SDAIS does not pretend otherwise. Quality emerges through structured iteration.

Refinement Loop

The Generate → Review → Refine loop repeats until the Reviewer reports zero violations and all acceptance criteria pass.

After the Generator produces an initial implementation, the Reviewer checks every [ANN] block against the RSF and against the actual code. The Reviewer is looking for a specific set of questions:

  • Does the code actually implement what (TASK) declares?
  • Are (PRE) conditions enforced in the implementation?
  • Are (POST) conditions achieved?
  • Is every (CONSTRAINT) label respected?
  • Is every active RSF item covered by at least one block with a matching (ORIGIN) reference?
  • Does at least one block for each AC confirm that acceptance criterion passes?

When violations exist, the Reviewer writes findings and the Refiner acts on them. When all findings in a block are resolved, the block is marked (VERIFIED) true. Blocks that are already verified are not re-examined in subsequent rounds unless their dependencies change. The loop terminates naturally when the Reviewer has no new findings to raise.

If a finding genuinely cannot be resolved without changing the requirements — perhaps the RSF specifies contradictory constraints that only become apparent in implementation — the Refiner marks it Waived — requires RSF amendment. This is not a failure state. It is a signal that the specification needs revision. The RSF version increments, the SemanticAuditor reruns on the new version, and the loop continues with the existing annotated codebase as context. Prior annotations carry forward; only the relevant units need regeneration.


RSF Is Always Authoritative

One rule governs every conflict in SDAIS: RSF wins. When the RSF and the Architecture Definition File disagree, the RSF wins. When the RSF and the generated code disagree, the RSF wins. No agent may silently reconcile a conflict — it must surface any disagreement as a finding and request human resolution.

This rule has a corollary that matters as much as the rule itself: no human may silently amend the generated code to work around a requirement. If the code needs to change, the requirement changes first, the RSF version increments, and the change flows back through the loop. The audit trail is never broken.

This is what makes the specification the source of truth in a meaningful rather than ceremonial sense. It is not the source of truth because someone declared it to be. It is the source of truth because the process makes it structurally impossible for it not to be.


The Vocabulary You Will Need

Working with SDAIS means working with a specific vocabulary. Here is a compact reference for the terms that appear most frequently:

RSF (Requirements Specification File) — The set of all versioned requirement Markdown files under sdais/rsf/v<N>/. The single upstream artefact for all AI activity.

RAR (Requirements Audit Report) — Finding files produced by the SemanticAuditor and Grounder. One file per finding, stored in sdais/rar/v<N>/ and never modified after creation.

ADF (Architecture Definition File) — A module decomposition and API surface document produced by the Designer. Stored at sdais/adf/v<N>/design.md. Optional, but valuable for complex systems.

[ANN] block — A structured comment block embedded in generated source code. The inter-agent protocol that carries intent, traceability, and verification state across all rounds and agents.

(ANN-ID) — A stable eight-hex identifier (ANN-7f3a9c2e) assigned at block creation and never changed. The permanent reference for a specific unit across the entire project history.

(VERIFIED) — The true / false flag set by the Reviewer on every block. A block is verified when no unresolved findings exist against it.

(ROUND) — The integer tracking which review round last touched a block. Starts at 0 (Generator output) and increments with each pass.

(ORIGIN) — The RSF item IDs that a block implements. The traceability link from code unit to requirement.

(FINDING:n) / (SEVERITY:n) / (HINT:n) — Co-indexed finding labels written by the Reviewer. n is a 1-based integer local to the block and never reused or renumbered across rounds.

(FINDING:n:STATUS) — The resolution record appended by the Refiner. Either Resolved — <rationale> or Waived — requires RSF amendment.

UNQUANTIFIED — A RAR finding category for NFRs without a numeric bound. One of six SemanticAuditor categories, alongside AMBIGUOUS, INCOMPLETE, CONTRADICTORY, INFEASIBLE, and UNTESTABLE.

RES (Re-engineering Specification) — Hypothesis files that capture prior knowledge about an existing codebase before the Analyzer runs. Status values: Hypothesis, Confirmed, Refuted, Refined.

CDF (Change Definition File) — A transformation specification for SDAIS-RE. One file per transformation dimension (lang-, pers-, mod-, api-, and others). CDFs are orthogonal — multiple CDFs can transform the same codebase in a single pass.


Re-Engineering as a First-Class Workflow

SDAIS is not only for new projects. The SDAIS-RE extension addresses the more common case: an existing codebase that was built without a formal specification and needs to evolve — to a new language, a new platform, a modular architecture, or simply needs a formal specification to exist at all.

The core insight of SDAIS-RE is that the inversion still holds — but you start from code instead of specification. The Analyzer agent annotates the existing codebase additively (never modifying existing logic), derives RSF items from observed behaviour, and opens RAR findings for anything that cannot be clearly mapped to a requirement. The result feeds into the standard semantic audit loop. Once the specification is cleared, Change Definition Files (CDFs) describe the desired transformations, and the Re-engineering agent applies them while preserving every (ANN-ID) value — maintaining the audit trail from original unit to transformed unit even across a complete language migration.

The (ANN-ID) values assigned by the Analyzer are permanent. A unit that begins its life as a Java method annotated with ANN-c9e05a31 will carry that same identifier into the Go implementation that replaces it. The identity of the unit persists across the transformation; only its implementation changes.


What Changes When Humans Stop Writing Code

There is a philosophical dimension to SDAIS worth naming directly. It is a shift not just in tooling but in what software development is.

When humans write code, the code is the primary creative act. The specification — if it exists — is secondary: a description of something already built, or a loose guide that will be diverged from as soon as the first implementation constraint is encountered. The developer’s judgment about how to solve the problem is expressed in the code, not in the requirements.

In SDAIS, the primary creative act is the specification. The developer’s judgment about what the system should do, what quality attributes it must satisfy, what constraints it must respect, what acceptance conditions will confirm it works — all of this is expressed in RSF items. The code is a consequence.

This changes what expertise looks like. Writing a good FR is different from writing good implementation code. Writing a testable, quantified NFR requires a different kind of thinking than optimising a hot path. The SemanticAuditor’s job — finding the AMBIGUOUS and CONTRADICTORY and UNTESTABLE in your requirements before they become bugs — is a forcing function for clearer thinking about what you actually need.

It also changes what the audit trail contains. In a traditional codebase, git history shows what changed. In an SDAIS project, git history shows what changed and why — because every (ANN-ID) is traceable to one or more RSF items, every RSF item has an audit history of the findings raised against it and how they were resolved, and every finding file records the reasoning behind each resolution decision. The chain from intent to artefact is not just maintained; it is documented at every link.


The following documents here will show step by step how to use the workflows for Greenfield and Re-Engineering projects. If you are interested earlier, then follow the development of the SDAIS project on Codeberg. Right now it reached the version v0.9.0.


The End of Specification Drift

SDAIS does not promise to eliminate complexity. Software is complex because the domains it models are complex, and no process changes that. What SDAIS promises is something more specific and, in practice, more valuable: the end of specification drift.

When the specification is the single upstream artefact and the code is always derived from it, the gap that normally opens between intent and implementation over time cannot open. Not because everyone is more disciplined. Because the structure prevents it.

That is the inversion. That is the idea.

One thought on “The Specification Is the Source of Truth: An Introduction to SDAIS

Comments are closed.