Code on GitHub →

The problem

Coding agents are strong on general software and weak on embedded firmware, for specific, addressable reasons: they can’t observe hardware state directly, they confabulate pin assignments and register values fluently and confidently, and bring-up work spans more sessions than a single context window holds. Rather than work around those failure modes ad hoc per project, I built the harness itself as the deliverable — infrastructure that makes agent-assisted embedded work verifiable, not infrastructure that papers over the gaps.

What it actually is

A two-part repository: an agent harness (bench daemon, hardware-fact provenance rules, a MISRA static-analysis gate, Renode emulation, hardware-in-the-loop flashing) and, built on top of it, STM32 firmware projects that report status honestly against an explicit verification ladder — L0 (builds) through L5 (a human physically confirms the hardware behaves correctly). A project states the highest gate it has actually reached; “L2 green, L4 not run” is the expected way to describe progress, not a failure to hide.

Technical decisions worth mentioning

  • Split trust model. The agent’s shell (cross-compiler, linter, Renode, git) never touches USB or hardware directly. A separate daemon (benchd) on the physical bench host exposes only five allow-listed verbs (inventory/flash/reset/serial/selftest) over a UNIX socket, refuses any board not in a human-edited inventory file, and requires a fresh human acknowledgement token before touching anything that spins, heats, or runs above 50 V.
  • Hardware-fact provenance. Every claimed pin, register, or clock value in docs/hardware/*.md carries a source: field (document, revision, section) and a verified/unverified status. Unverified facts can’t be used in code. In practice this caught a real mistake mid-project: a seeded fact sheet assumed one board was the official STM32F072B-DISCO; reading the actual schematic and running st-info against the physical board showed it was a different board revision entirely (an older 32F0DISCOVERY PCB later populated with a different MCU) — the wrong assumption was corrected before any driver code was written against it, not after.
  • MISRA C:2012 gate with recorded deviations, not a suppressed report. cppcheck --addon=misra plus clang-tidy run in CI; real deviations (e.g. early-return clamping in a quantization routine, technically MISRA 15.5) are recorded as ADRs with the rule number, the construct, why the compliant alternative is worse, and the containment — not blanket-suppressed to get a green check mark.
  • CubeMX generates the linker script and startup code, not me. Hand-writing memory maps and vector tables is exactly the class of task an LLM will get plausibly wrong; the harness’s own CMake structure is designed so CubeMX’s own export slots in without being touched by hand.

Status, honestly

The toolchain image, bench daemon, MISRA gate, and verification-ladder tooling are built and exercised. The first firmware project (quantized inference on a memory-constrained Cortex-M0 target) has its host-testable logic passing L0/L1/L2 against the real toolchain container; the cross-compiled/on-hardware gates are queued behind generating the CubeMX project for the target board.