Verification and validation: a handbook chapter for how edakit is tested¶
A source
This page is a source of edakit – a concept, a prompt or the rules of a session –, shown as it is in the repository. Read it as such; the guides say what edakit does.
Status 2026-11-03: concept, asked for by the owner the same day – "I have the feeling our extensive V&V setup gets
lost in the documentation. Proposal: a chapter of its own in the handbook with the test setup, the reference circuits
included, and their description – why exactly these, what must be true to add another one, …". Written against main
at dc561ef; every number below counted there. Decided by the owner the same day in a decision round (decisions 1 to
4 as recommended, Claude's own decisions confirmed – "Decisions" at the end). VV.5 done the same day: TD-118 to
TD-121 in TODO.md. Built the same day on the owner's word ("Mach alle diese todos") and merged on the owner's
OK as edakit 1.1.4 (#281): VV.1 to VV.4 – handbook chapter 19 – and the four open designs TD-118 to TD-121; moved to
done/. The known gaps the new designs showed are TD-124 to TD-133.
Why¶
edakit is tested in nine layers, from synthetic engine tests to published open designs, live runs at the makers and evals with two models. A reader meets them in pieces:
| Where | What it says about the testing |
|---|---|
docs/working-on-edakit.md, "Tests" and "Evals" |
four sentences on the test layers, three on the evals, a list of the documentation's tests |
docs/adding-a-rule.md, "Seen red once", "Against real circuits" |
a new rule is seen red on led-bar and runs on the reference circuits and the open designs |
| handbook 14.3 | the drawing of the reference circuit power and one sentence: "Each domain has such a reference circuit" |
| handbook 14.4 | edakit mutate on led-bar (24 of 45 caught without the simulation, 43 with it) and one sentence on the seeded faults |
| handbook 5, 8, 16 | single tests by name: test_sim.py, test_fab_run.py, the CI job kicad, the live runs in tests/fixtures/makers/LIVE.md |
catalog pages circuits.html, open-designs.html |
the most complete view: every reference circuit drawn with its seeded faults, every open design with its judged findings – generated, without a reason for the choice |
docstrings of tests/reference.py, tests/test_open_designs.py |
the only list of the open designs with source and licence |
evals/README.md |
the cases and the baseline – a source, not documentation |
docs/concepts/done/rules-at-scale.md section 7, maker-coverage.md FT-21, FT-24 and guardrail 5 |
why the layers exist and which circuits were meant |
No page answers the questions a reader has: what a clean edakit check proves and what not; why these seven
reference circuits and these six designs; what the judgements real, lacks, criterion and known gap mean; what a new
reference circuit or open design must bring. By the yardstick (docs/concepts/done/design-as-text.md), the admission
rules exist only as assertions in tests/test_reference.py and tests/test_open_designs.py and, for the choice, in
someone's head.
What exists¶
The inventory at dc561ef: 151 test files with about 2000 test functions, 9 eval cases.
| Layer | Where | What it proves | Kind |
|---|---|---|---|
| 1 Engine tests | tests/test_engines.py |
every relation fires on its fault and on nothing else, on small synthetic circuits; LIMITS and PATHS hold their properties at random values | verification |
| 2 Seen red once | tests/fixtures/led-bar and test_checks.py (73), test_sim*.py, test_gate.py (35), test_fab_run.py (52), many more |
every check fires on a fault built into a copy of the example, and the repaired copy is clean | verification |
| 3 Reference circuits | tests/reference.py, tests/test_reference.py |
one circuit per domain, built onto led-bar, passes clean under its domains; each of its 15 seeded faults raises exactly its codes and no other (the overlap test) | verification |
| 4 Wrong judgements held | test_false_alarms.py (17), test_wrong_judgements.py (12), test_open_design_fixes.py (18) |
each false alarm once found: the circuit where the finding was wrong stays quiet, the one where it is right still raises it | validation |
| 5 Open designs | tests/open_designs/ (6), tests/test_open_designs.py |
published designs transcribed as published; what check and sim find is exactly what findings.toml judges – 149 findings: 51 real, 58 lacks, 39 criterion, 1 known gap |
validation |
| 6 Mutation sweep | edakit mutate, test_mutate.py |
which built-in mistakes no code catches – a list for reading | validation |
| 7 Documentation held to the code | test_walkthrough.py, test_walkthrough_kicad.py, test_quickstart.py, test_references.py, test_style.py, test_catalog*.py, test_pages.py |
what the walkthroughs and the quickstart quote still holds; every named section exists | verification |
| 8 Live against external tools | CI job kicad (test_kicad_live.py, KiCad 10), tests/fixtures/makers/LIVE.md, the EasyEDA live test of led-bar on 2026-10-31 |
KiCad reads what edakit writes; the cart skill at four makers; the EasyEDA tool chain end to end | validation |
| 9 Evals | evals/, claude plugin eval |
Claude with the plugin finds a seeded fault, reports the coverage, adds an LED – with Sonnet and with Opus | validation |
Verification asks whether edakit does what its rules say; validation whether the rules fit real circuits and the whole helps a maker. The split is the chapter's spine: it tells a reader which layer answers which doubt.
Two observations from the inventory, for the chapter and not as faults:
- The open designs are a tripwire. A new rule that fires on one of them fails
test_open_designs.pyuntil the finding is judged. That is how "a new rule runs on the open designs" (docs/adding-a-rule.md) is enforced; the skill add-rule names only "the projects at hand" (step 6), which are the owner's projects outside the repository. - Some validation is not repeatable from the repository. The owner's projects (the bell, pytree), the EasyEDA live test and the makers' live runs need the owner's machine or accounts. The chapter says which layer a reader can rerun.
The reference circuits¶
All seven are edakit's own, shaped after common maker designs and built onto led-bar: parts from the block library's
checked entries, and test entries numbered C91000xx with "values for the reference circuit, not from a datasheet"
where the library lacks one. Synthetic on purpose: each fault must raise exactly its codes, which needs a circuit
that is clean without it.
| Circuit | Domain | The circuit | Seeded faults → codes |
|---|---|---|---|
motors |
motors | a 33 Ω motor switched low-side by an S8050, flyback diode SS14 | no flyback diode → REQ.missing; a 10 Ω winding → LIM.i, LIM.p |
audio |
audio | class-D amplifier fed from a PWM pin through a 1 kΩ / 10 nF low-pass, bridge-tied to an 8 Ω speaker; an AC run expects 15.9 kHz | an output on ground → REQ.forbidden; the filter capacitor ten times larger → SIM.response |
guitar |
guitar | instrument buffer: jack, 2.2 MΩ bias to a half-supply reference, op-amp follower, 1 µF / 100 kΩ output coupling at 1.6 Hz | bias 470 kΩ → REQ.value; reference above the input range → LIM.range; bypass switch to 0 V → REQ.value; coupling ten times smaller → SIM.response |
power |
power | three AA cells beside USB through an SS14 onto +5V | the cells' current limit → LIM.i; no diode → PATH.reverse |
cables |
cables | a button on a hand-wired remote board, 1 m of AWG 26, 1 kΩ series and 10 kΩ pull-up at the pin | no series resistor → REQ.missing |
usb |
usb | USB-C receptacle for data: Rd 5.1 kΩ on each CC, D+ and D− of both rows joined, 27 Ω to the MCU | D+ of one row only → REQ.missing; no Rd on CC2 → REQ.missing |
keyboard |
– (rules for every board) | 2 × 2 key matrix, a diode per key, cathodes to the rows | a key without its diode → REQ.missing; a diode turned round → REQ.forbidden |
test_every_domain_has_a_reference_circuit holds one per domain except radio (a transmitter's facts, no circuit of
its own – covered by the ESP32 DevKitC) and mains (recognised, not checked; its fault is built into the example in
test_hazardous.py).
The open designs¶
| Design | Licence | What it brings that the reference circuits lack |
|---|---|---|
esp32-devkitc-v4 |
none stated – only the circuit's facts | usb, radio and power in one board; the only real transmitter |
sparkfun-logic-level-converter |
CC BY-SA 3.0 | four BSS138 channels, level shifting in both directions simulated |
corne-cherry-left (v4) |
CC BY 4.0 | RP2040 with USB-C, 23 keys on direct pins, a chain of 23 SK6812MINI-E one diode below 5 V |
corne-cherry-v3-left |
MIT | a real key matrix of 21 keys with a diode each, Pro Micro, 27 RGB LEDs |
guitarml-classic-boost |
MIT | a discrete common-emitter stage, its bias across the hFE spread (FT-17) |
guitarml-ts-rat-combo |
MIT | op-amp and JFET stages, a 3PDT order switch; a reversed electrolytic found real |
FT-21 (maker-coverage.md) named further candidates that are not built: a WLED controller, a Fuzz Face, a relay board
with an HLK-PM01, a LiPo charger.
The chapter¶
Handbook chapter 19, "Verification and validation: how edakit is tested", file handbook/19-verification.md,
in the group "Reference" of the handbook's index, read when "you want to know how far a finding or a clean check can
be trusted, or you add a reference circuit or an open design". Register: a guide (docs/style.md), at most 500
lines.
Why the handbook: docs/organisation.md keeps the handbook for those who use edakit, and the chapter's first question
is a user's – what does a clean check prove? The reference circuits are shown to users already (14.3, the catalog).
And the admission rules are needed by whoever proposes a circuit, a project with /edakit:propose-feature included.
The step-by-step for a session stays where sessions read it (docs/working-on-edakit.md, the skill add-feature), and
links to the chapter.
| Section | Content | Written |
|---|---|---|
| 19.1 What the testing proves | what a clean check and a clean simulation mean, and their limits: findings rest on part facts (--coverage), the reference circuits' test entries are not real parts, a known gap is a known wrong judgement, the regulatory review is support and not legal advice (15) |
by hand |
| 19.2 The layers | the table above, each layer with what it proves, verification or validation, where it runs (CI jobs test and kicad, by hand, evals) and whether a reader can rerun it |
by hand |
| 19.3 The example led-bar | the base every fault is built into: 17 parts, 18 nets, MCU, LED driver, connector, reverse diode, button; why a fixture of its own beside the walkthrough examples of chapters 17 and 18 | by hand |
| 19.4 The reference circuits | one entry per circuit: what it adds, why this circuit for its domain, its seeded faults with their codes, a link to its drawing in the catalog | generated |
| 19.5 The open designs | one entry per design: source, licence, why chosen, its findings counted by judgement, its known gaps | generated |
| 19.6 How a finding is judged | real, lacks, criterion, known gap – what each means, and how a user reads the same words on their own findings | by hand |
| 19.7 Adding a reference circuit or an open design | the admission rules below, and the way in: a proposal from a project, or the skill add-feature in the repository | by hand |
| 19.8 The evals | what they measure, the cases, the baseline, how to read a score – one run is a reading, not a rate | by hand, the baseline quoted from evals/README.md |
| 19.9 What is not covered | radio and mains without a reference circuit, the open candidates of FT-21, the known gaps, what edakit mutate leaves on led-bar, the stages that only live runs reach |
by hand, the counts generated |
Generated, not copied. 19.4 and 19.5 list values, faults and counts that change with every circuit, fault or
judgement. Copied by hand they drift, as the catalog's own pages would. They are generated, as the handbook's tables
of codes are, between <!-- edakit:generated … --> markers, from tests/reference.py (REFERENCES, FAULTS, the
docstrings) and from each design's README.md and findings.toml; a test fails when the chapter is out of date. The
"why" of each circuit and design moves into those sources (VV.1), so that the catalog page and the chapter say the
same.
The admission rules¶
What a new one must bring – the chapter's 19.7, held by tests where they can be counted (VV.4).
A reference circuit (tests/reference.py):
- A gap of its own. It brings a domain no reference circuit covers, or a family of codes of a covered domain that no seeded fault raises yet. A new domain needs one (held already).
- Built onto led-bar as one function in
REFERENCES: designators from 20, the MCU pins it uses freed, a block of its own in the drawing, the board titled "Reference:". - Its parts named honestly. The block library's checked entries first; a test entry only where the library lacks
one, numbered
C91000xx,verified.by = "reference circuit", its source "values for the reference circuit, not from a datasheet". - Clean. No error, warning or pending finding in check, no row of the simulation that fails or warns; its domain switched on by the graph alone (held already).
- Its faults exact. At least one seeded fault per family of codes it is there for, each a mistake a maker makes, each raising exactly its declared codes (held already); a fault only the simulation shows where the domain has a rule of the simulation.
- Described. The docstring says what the circuit is with its values; a
whysays why this circuit stands for its domain. Both are what 19.4 shows. - Small enough to read. Drawn on one page by
edakit schematic draw(the catalog page).
An open design (tests/open_designs/<name>/):
- Published, and the licence allows it. A schematic anyone can open; its
README.mdnames the source with its commit or revision, the licence – a CC licence with its URI –, and every change; a row inREADME.md's licence table (held already). Without a stated licence only the circuit's facts are transcribed, not the drawing. - Something the others lack. A domain or a circuit class no reference circuit and no open design covers, with real parts and their datasheets; preferably a design makers build and copy, so that a false alarm there would meet many.
- Transcribed as published. Not repaired; a stand-in for an unnamed part named in the README; every parts entry names its datasheet and fits the schema (held already).
- Every finding judged. Each finding of check and sim in
findings.tomlwith its judgement and a reason (held already); a false alarm it shows is fixed and held intest_open_design_fixes.py, or kept as a known gap with the reason. - Described. A
whyline in its README: what it brings – what 19.5 shows.
Steps¶
| Step | What | Where | Lane |
|---|---|---|---|
| VV.1 | The descriptions into the sources: a why for each of the seven reference circuits and six open designs, written from the tables above and checked against maker-coverage.md FT-21 |
tests/reference.py, tests/open_designs/*/README.md |
branch |
| VV.2 | The generator: 19.4, 19.5 and the counts of 19.9 written from the sources, a test that fails when the chapter is out of date | docs/catalog/build.py (it reads tests/reference.py and tests/open_designs/ already), a test beside tests/test_catalog_page.py |
branch |
| VV.3 | The chapter: the sections by hand; the handbook's index, docs/pages.py (NAV), docs/organisation.md ("chapters 1 to 19"), the glossary (reference circuit, open design, seeded fault, seen red once, the four judgements); docs/working-on-edakit.md, docs/adding-a-rule.md, handbook 14.3 and 14.4 link to it, their statements kept in their sections |
handbook/, docs/ |
branch, a fragment patch – the handbook is outside NO_VERSION |
| VV.4 | The countable admission rules as tests: a test entry of a reference circuit numbered C91000xx and marked; a why for every reference circuit and every open design |
tests/test_reference.py, tests/test_open_designs.py |
with VV.1 |
| VV.5 | The open candidates of FT-21 – WLED controller, Fuzz Face, HLK-PM01 relay board, LiPo charger – each as an item in TODO.md, each built later through the admission rules – done 2026-11-03: TD-118 to TD-121 |
TODO.md |
notes lane |
VV.1 to VV.4 are one branch (TD-117); the chapter is the work, the generator keeps it true.
Decisions¶
Taken by the owner on 2026-11-03 in a decision round, each as recommended; the alternatives stay for the record.
| # | Question | Decided | Not taken |
|---|---|---|---|
| 1 | Where the chapter goes | handbook chapter 19: the trust question is a user's, the reference circuits are shown to users already, and proposals come from projects | a reader page docs/testing.md beside docs/working-on-edakit.md, for developers only; a section 14.7 in "Designing a circuit" |
| 2 | How 19.4 and 19.5 are written | generated from the sources, the "why" moved into them: seven circuits and six designs with values, faults and counts drift when copied | by hand, held by a test that only checks every name appears |
| 3 | The admission rules | as above, held by tests where they can be counted | as text only; only what the tests hold today |
| 4 | FT-21's open candidates | named in 19.9 and listed in TODO.md, built later one by one |
built with the chapter; dropped |
Decided by Claude and confirmed by the owner the same day: the number 19 and the file handbook/19-verification.md;
the group "Reference" in the handbook's index; the split verification / validation as the chapter's spine; the steps
VV.1 to VV.5, VV.1 to VV.4 one branch with a fragment patch; the step-by-step for sessions staying in
docs/working-on-edakit.md and the skill add-feature; VV.5 done at once as TD-118 to TD-121, the chapter's build as
TD-117.