Chapter 21

Wednesday morning

Trace one batch by state and begin the software model with an outer test.

On this page

On Wednesday morning, July 15th, 2026, I lifted the lid on the brass tumbler and poured its output into a tray. I expected clean 5.56 brass. That was most of what I had loaded the night before.

Mostly.

Clean 5.56 cases came out with some 9mm, a few .50 caliber cases, and a stripper clip. The 9mm had slipped in unnoticed. The .50 caliber cases had been included deliberately. The stripper clip was not a case at all.

Nothing about the tumbler looked broken. Every object was cleaner than when it entered. The machine had done its one job, including on the things the next part of the system could not use.

That tray is where the tutorial's drawing begins to move. Up to now we have looked at parts, connections, rejections, swaps, and decisions. Now one batch has to travel through them. A drawing that cannot explain what happens to the stripper clip is incomplete. A drawing that loses the 9mm is dishonest. A drawing that cannot say what is known about the 5.56 at each step is only a floor plan.

A loading block of cleaned 5.56 cases beside larger cases, smaller pistol cases, and a stripper clip
One tumbler output contains expected material, wrong-context material, and a foreign object. The next boundary owes all three an explicit destination.

Follow state, not activity

It is easy to describe the morning as a list of work:

  1. Clean.
  2. Sort.
  3. Decap.
  4. Prepare the primer pocket.
  5. Size and trim.
  6. Inspect.
  7. Load.

That list tells us what the operator does. It does not tell us what the system knows.

Take one 5.56 case from the tray. Before cleaning it was a candidate: recovered material, dirty, mixed with whatever the range bag collected. After the first cleaning, one fact changed. The case was free of range dirt. Its caliber had not been admitted into this process. Its primer pocket had not been checked. Its length had not been measured. Nobody had established that it was safe to load. Later production would show why calling that one fact simply clean was too broad.

Activity is not state. Passing through a machine is not proof that every fact the next machine needs now holds.

The trace below makes that distinction explicit. It preserves the first working model and records the later physical evidence without upgrading the live-ammunition line.

Point in the journey State established here Decision owner Possible exit Evidence status
Range bag identity not yet trusted none; still a candidate none yet observed
Loading block expected caliber and case-like shape classification boundary wrong-context bin or foreign-material exit observed
Dillon preparation pass primer removed and full-length sizing performed configured station owns the transformations calibration scrap or work continues to measurement observed
Headspace inspection measured acceptance after sizing operator with gauge and acceptance policy rework observed and measured
Readiness line current required facts hold together readiness gate rejection with every failed reason evolving working model; not crossed by the fifty-case set
Progressive live-ammunition line primed, charged, seated, crimped, position by position production line held plate on fault designed, not yet live-proven

Five more stations run the same five questions; the full station-by-station trace lives on The Lab Ledger, with current counts and open obligations.

Read the table across, not only down. Every row answers five questions:

  1. What changed?
  2. What became knowable?
  3. Who owns the decision at this point?
  4. Where can the material leave the main flow?
  5. What kind of evidence supports the claim?

Those questions stop a common substitution. We stop saying, "it was processed," when what we mean is, "we hope the facts downstream needs are true."

Start with the body walking

Before designing a classifier, a readiness gate, or a press, write the smallest test that makes the whole intended behavior visible. In this lab that is a system-level acceptance test around one production entry point. It uses the real objects we own and substitutes only the station that produces the fault we need to observe.

The test starts with four inputs:

  • one ready 5.56 case;
  • one 5.56 case whose sized fact is false;
  • one 9mm case;
  • one stripper clip.

It also starts with the provenance a completed batch will need: load specification, brass lot, and component lots. Mid-run, the powder station faults once.

This was the first assertion:

it "stops at the first station fault instead of silently retrying" do
  result

  expect(charge.attempts).to eq(1)
end

The first run was red because the production orchestrator kept cycling. The fake station failed once and then succeeded, which exposed the dangerous behavior precisely: the system could make a fault disappear by trying again. On a progressive press, advancing after a station failed can turn a located problem into an ambiguous cartridge farther around the plate.

So the outer test asks for more than a stopped loop. It asks the system to return the partial truth:

it "returns a halted result with the fault and a derived recovery plan" do
  expect(result).to have_attributes(
    halted?: true,
    faults: contain_exactly(
      have_attributes(
        station: "charge", status: :faulted, fault: :powder_hopper_empty
      )
    ),
    recovery_plan: contain_exactly(
      have_attributes(
        station: "charge", disposition: :resume, missing: []
      )
    )
  )
end

And it refuses to let the earlier exits vanish merely because a later stage failed:

it "preserves every exit decided before the production fault" do
  expect(result.rejected.map { |kase, _| kase }).to eq([unsized])
  expect(result.rejected.first.last.reasons).to eq([:unsized])
  expect(result.wrong_context).to eq([nine_millimeter])
  expect(result.foreign).to eq([stripper_clip])
end

The complete test is in spec/reloading_lab_spec.rb. It is green now. That does not convert the modeled production event into an observed garage event. It proves that the Ruby body walks according to the contract we wrote. The first live batch is still a different kind of proof.

Why this test comes before the parts

The test does not yet tell us how many classes to write. It tells us what must enter the system, what must remain visible, where control returns, and what shape the answer must have. Those are body-plan claims.

If we began with a CaseClassifier, we could produce excellent DNA for one part while missing the fact that a production fault must preserve classification exits. If we began with the press, we could make its cycle beautiful while forgetting provenance. If we began with the batch record, we could record completed work and have no honest representation of a halted run.

The outer test forces all of those parts to belong to the same creature before we perfect any of them.

It also gives the inner tests a court of appeal. Later, a unit test may claim a collaborator protocol works because its mock returned the expected shape. The outer test runs the owned objects together. If the unit tests pass and this test fails, the doubles told a convincing lie.

This is the walking skeleton: the smallest end-to-end behavior that exercises the load-bearing path. It need not be complete. It must be complete enough to fail on behavior, not on missing plumbing. A useful red says, "the run retried the fault." A useless red says, "constant not found."

Make your own trace

Choose one thing that moves through a system you know: an invoice, a support case, a deployment, a new employee, a shipment.

Do not list the screens it visits. Trace its state.

Point State established Decision owner Possible exit Evidence

Then write one outer test in ordinary language before you name the classes:

Given ________, when ________ happens, the system returns ________, preserves ________, and refuses to ________.

Make the test carry at least one successful path, one expected refusal, and one interrupted path. Include the identity or provenance a future operator would need. If the sentence forces you to invent several unrelated entry points, your body plan may still be hidden.

What this trace cannot prove

A state trace records the model we currently believe. It does not make the model true.

The magnifier has already improved what can be seen at the inspection point. The quarantine bag has already received damaged cases. The six-fact readiness line is a working synthesis, corrected once when sized was missing. The halt-and-recover path is executable in Ruby. None of that is evidence that a full production run will reveal no seventh readiness fact, no unexpected station interaction, and no new exit.

That is why the evidence column stays in the artifact. Without it, a clean diagram quietly turns designed behavior into remembered history.

The next chapter returns to the Wednesday tray. Before the expected 5.56 can move forward, the other material needs honest destinations.