Skip to content
The record
Report3 October 20265 min read

A first vertical slice through four languages, and two defects only real hardware output exposed

Phase 1 built one JSON Schema contract and a thin slice through a Rust hardware core, a C# Windows agent, TypeScript validation and a PostgreSQL ingest, and checking real output on a Lenovo laptop exposed two defects the existing tests had missed; once both were fixed, with new tests, the gate passed 45 of 45 tests.

systemshardware-testingmethod

What was done

Built the repository, the architecture documents and a thin end-to-end slice through every layer of the prescribed stack: one canonical JSON Schema contract, a Rust core that reads real hardware on Windows and Linux, a C# Windows agent that continues an open diagnostic session, and TypeScript validation with a PostgreSQL ingest library tested on a real database engine. Every hardware value in the contract records whether it was actually measured, where it came from, and why it is missing if it is. During verification, checking the real output on the development laptop exposed two defects the existing tests had not caught, a misleading CPU base clock and an agent crash on relative paths. Both were fixed, with new tests, before the commit, and the gate then passed 45 of 45 tests.

 CPU base clock: which source is believed?
 
 1. CPUID leaf 0x16      masked by the Windows
         |               hypervisor on this laptop
         v  no value
 2. rated frequency      read from the processor
    in the brand string  brand string
         |
         v  no value
 3. WMI MaxClockSpeed    still recorded, but labelled
                         "unverified as base"
 
 seen before the fix: WMI said 2101 MHz
 for a part rated at 1.6 GHz

A documented order of sources, and the last resort says what it is.


Status

Shipped, 3 October 2026 (commit dc6b7dd, 13:33 BST): 71 files, 9,916 insertions.

The first of the specification's 23 phases, each of which ends at a verification gate.

The problem

The project's specification forbids faked hardware data and requires evidence before conclusions. A diagnostic system that silently fills a missing reading with a plausible guess breaks both rules, and the break is invisible in the output. The first phase therefore had to put those rules into the data itself, and prove that every language boundary in the stack could carry them, before anything was built on top.

What was built

  • One contract. A single JSON Schema (draft 2020-12) is the canonical definition of a diagnostic session. The Rust, C# and TypeScript types are written by hand and each language's test suite validates them against the schema, rather than generating code from it.
  • An evidence unit for every fact. Each hardware value carries a status (available, unavailable, not applicable or mock), the value, its source and its unit. An unavailable value must carry the error that explains it, and mock data is labelled as mock.
  • A Rust core of three crates, one of them the diag command-line tool. Real providers read CPUID; Windows through WMI, the registry and Win32 firmware calls (including read-only Secure Boot state); Linux through sysfs and efivarfs.
  • A C# Windows agent that finds open sessions, asks the Rust core to continue them, and never modifies another machine's session or a mock one.
  • TypeScript validation and a PostgreSQL ingest with append-only storage, tested on real PostgreSQL running in-process through PGlite.
  • Six architecture documents and six decision records, and a GitHub Actions workflow.

How it was built

The owner, Stephen Ukaegbu, supplied the specification and made the scoping and tooling decisions. The engineering was AI-assisted: Anthropic's Claude Code worked as lead engineer, planning and implementing the phase against the specification. This phase was designed directly by the lead (from the working-session log); the panel-and-critique design method used in Phase 2 was not applied here.

How it was proved

45 tests passed, 0 failed, 0 skipped: 21 in Rust, 8 in C# (xUnit), 16 in TypeScript (Vitest). Rust formatting and Clippy with warnings as errors were clean, and the .NET build had 0 warnings under warnings-as-errors.

The tests include a real scan of the development PC validated against the schema, three C# integration tests that drive the real Rust core (continue a session; refuse another PC's session without modifying it; refuse mock data), and real core output validated by ajv. A manual end-to-end run on the laptop created a session with the core and continued the same session ID with the agent, leaving two segments, the first marked ended.

The real-hardware machine was a Lenovo laptop: Intel Core i5-10210U, 16 GB DDR4, SK hynix 512 GB NVMe, Intel UHD Graphics, Windows 11 Pro 25H2, UEFI firmware with Secure Boot disabled.

The two defects

A wrong CPU base clock. WMI reported 2101 MHz for a processor rated at 1.6 GHz. The direct source, CPUID leaf 0x16, was masked by the Windows hypervisor, because the machine runs virtualisation-based security. The fix is a documented order of sources: CPUID first, then the rated frequency in the processor brand string, then WMI, labelled "unverified as base". A unit test was added.

An agent crash on a relative path. Giving the agent a relative path to the core made it crash with an unhandled Win32 exception. The path is now resolved to an absolute path, and a launch failure is reported as a failure instead of thrown. Two tests were added.

Both were found by checking real output against known facts about the machine, not by the automated tests that existed at the time.

What was deliberately not built

  • No bootable image. Booting under UEFI, Secure Boot and Legacy BIOS is design only at this stage. Detecting UEFI against BIOS, and reading Secure Boot state, from inside a running operating system is implemented and tested. Nothing in the codebase writes firmware variables, and customer-facing wording is tested never to suggest disabling security.
  • No Linux execution. The Linux target was type-checked and linted, but not run.
  • No CI run. The workflow was written, but there was no remote repository for it to run against.

Limitations recorded at the gate

The Linux providers had no memory-module or GPU detail and need root for identity. CPU maximum boost clock is reported as unavailable when CPUID leaf 0x16 is masked. Whether the SMBIOS system UUID is byte-ordered the same way under Linux and Windows was unverified. Local Node was version 20, past end of support, while the CI workflow uses 24.

Open questions

Whether the SMBIOS system UUID is byte-ordered the same way under Linux and Windows is unverified.


The code

The source precedence for the CPU base clock: each branch records which source it trusted, and the last resort labels itself.

// CPUID 0x16 can be masked by the Windows hypervisor (VBS), so fall back to the
// rated frequency in the brand string. Win32_Processor.MaxClockSpeed is last: on
// some laptops it reports neither base nor boost (e.g. 2101 MHz on a 1.6 GHz part).
let base_clock = match (id.base_mhz, brand.value().and_then(|b| decode::brand_rated_mhz(b))) {
    (Some(v), _) => Observation::available(v, "cpuid:leaf0x16").with_unit("MHz"),
    (None, Some(v)) => Observation::available(v, format!("{}:rated-frequency", brand.source)).with_unit("MHz"),
    (None, None) => n(
        rows.first().and_then(|r| r.max_clock_speed),
        "wmi:Win32_Processor.MaxClockSpeed (unverified as base)",
        "MHz",
    ),
};
From core/hardware/src/windows.rs — an excerpt, trimmed to the technique it illustrates; identical in the Phase 1 commit and the current committed version.

Not shown. The session-continuity check that decides whether a found session belongs to this machine, and the machine fingerprint behind it, are withheld: that is the identity control that stops two PCs' evidence being merged, and it is still in use.

A published copy. Commit references and internal identifiers have been removed and the operator is not named; the engineering, the counts and the stated limits are unchanged.