One Spec to Rule Them All: a single source of truth for firmware, tests and docs

Embedded Systems Software Agentic Engineering

Agentic engineering is a software development discipline in which humans define goals, constraints, and quality standards while AI agents autonomously plan, write, test, and evolve code under structured human oversight.

As the methodological basis we use spec-driven development (SDD), an approach that treats specifications as executable contracts and derives the code from them. The methodological comparison with waterfall, Scrum® and SAFe® sits in its own article: Spec-driven development, Scrum, SAFe, and waterfall — what works when →

The concrete form we have chosen for our embedded devices is a single source of truth (SSOT) in JSON, from which firmware, tests and manual are generated. This article describes how that looks in practice.

The experience reported below is based on Claude™ Opus 4.7 with a 1 M context window, run in modes high through max.

The architecture in one picture

A lean message bus (not much more than a mailbox per role, with persistence) connects several AI instances. Together they run a largely autonomous cycle of firmware, test and interface documentation for our embedded devices.

We staff five roles, all by AI instances:

The human sits outside the cycle. The goal is to take the human out of the loop as far as possible. They step in when something jams, and they decide the questions that cannot be delegated: architecture, customer wishes, prioritisation, final sign-off.

Reality adds plenty of surprises that pull you back to the keyboard whether you wanted to or not: Windows® reboots the host, Claude has an outage, the credits run out, or the Tortoise cache runs amok again and freezes the system with its wild indexing.

The problem: drift

An embedded device has an interface, a list of values with address, type, allowed range, default and meaning. That contract has to be true in three places at once: in the firmware, in the tests and in the manual.

In normal practice those three copies start drifting apart almost immediately. Someone widens a value range in the firmware. The manual still shows the old range. A test still asserts the old maximum and starts failing for the wrong reason. Six months later nobody is sure which of the three is right.

The only lasting cure: stop maintaining three copies and maintain one.

The SSOT in JSON

The interface contract lives in a single, version-controlled JSON file. Every change is fully traceable through the version history. Every value is defined exactly once and carries everything anyone downstream needs: address, data type, permitted range, named states, access rules (read-only, read/write, protected), power-on default, and a plain-language description.

JSON because a machine can read it directly. The spec becomes human-readable through the documentation generator that produces a complete interface reference from it. There are not two formats (one for machines, one for humans), there is one format and a generator.

What gets generated

From that file we regenerate, on every change:

The spec is not flawless from day one. A wrong range, a forgotten state, an unclear description is part of normal iteration. Such errors are fixed in the spec, then everything underneath is regenerated. As the spec matures, this happens less and less often.

The human does not edit the JSON file by hand; a request to the domain expert / spec owner is enough. And in the generated documentation everything is presented in human-readable form, ready for thorough review.

Testing on the real target

Every iteration is tested on real hardware, a setup known as hardware-in-the-loop (HIL). Reason: timing and concurrency bugs only show up there. Simulating the target’s full hardware is only partly possible, so the simplest path is to run on the device itself.

The agents do have additional skills for pre-clarification: analyse code statically, run scripts locally on the host, exercise a simulation of the device. A lot is resolved up front; not every question has to go to the target. For the final verdict though, the silicon is the judge, and it is measured against the spec.

Audit gates: the build stops on drift

Generation alone is not enough. Someone can still re-introduce drift by hand, so the build (not just the tests) fails on violations:

The checks are boring. That is exactly the point. “Please keep everything in sync” turns into “the build refuses to continue if you didn’t”.

There is a balance to strike between iteration speed and quality. My favourite instruction to the agents on that: we cut the old habits loose. And we do it now. From the agent’s point of view that is in plain contradiction to the equally valid rule “the codebase is stable and mature, we only make minimal changes”. Living with both at the same time is part of the job, for humans and agents alike.

The spec wins

When behaviour and spec disagree, that is a bug in the firmware or a mistake in the spec, never a licence to quietly adjust the test. The fix always flows in one direction:

change the spec → regenerate → build → flash → re-run the HIL sweep.

That single rule is what keeps the source of truth actually true over years. It also makes multi-language docs a non-event: edit the master language once, translation flows one way.

In practice a spec change unfolds like this. The agents talk to each other in natural language. The firmware developer runs into a register value whose behaviour the test agent considers wrong. On request, the firmware developer explains the implementation, and together they work out a fix. A short cross-check that the problem really was understood is part of the loop. The change is then reported to the domain expert / spec owner, who in most cases can apply it and communicates the adjustment to the affected places.

Skills, rules and typical problems

Every role gets clear skills. When we see a problem in behaviour, we refine the skills or the rules rather than papering over the issue. What strikes us repeatedly: the agents imitate human behaviour in real teams quite closely. Three classics:

These patterns are the same ones every engineering manager knows from real teams. They disappear with clear skills, clear rules, and a spec that settles every dispute.

Field anecdotes

Workflow: humans sit outside, agents drive build and test across several testbeds, triage against the spec The spec is the guard rail. The cycle drawn here is only triggered when the JSON spec needs to change. The autonomous ping-pong between test agent and firmware runs separately and continuously.

What we deliberately did not build

No heavyweight orchestration framework. The machinery stays small: one spec file, a set of generators, a hardware test runner, a handful of audit checks, a lean bus. Small enough that a new engineer can read the whole thing in an afternoon.

Takeaways

Functional tests that are relevant to certification run outside this cycle, with their own protocols, audit trails and sign-offs.

Keywords: Single Source of Truth, Spec Driven Development, Agentic Engineering, firmware code generation, Hardware in the Loop, JSON interface contract, AI agents firmware consulting, audit gates, Claude Opus, embedded HIL testing, Embedded Consulting Switzerland, swissEmbedded firmware engineering

Are firmware, tests and manual drifting apart in your project? We build the single source of truth pipeline that generates all three from one contract and checks them against real hardware, from the JSON schema through the generators to the automated HIL testbed.

Contact us →