The factory workshop · Rod Rivera
Run the application before automating changes
Before you ask an agent to change an application, make sure you can tell whether that application works. Our application updates a synthetic customer’s email address. The interesting case is a request that succeeds at the receiving system but loses its response on the way back.
By the end of this lesson, you should be able to explain why “I didn’t receive a receipt” and “the update didn’t happen” are different statements.
Prepare your machine
Download the complete project and unzip it. Open a terminal in the dark-software-factory-v1 folder. You need Python 3.11 or later on your computer and a running Docker engine. The application itself runs in a pinned Python 3.13 container. No Python packages are installed on your host.
python3 --version
docker info
If docker info cannot reach an engine, start Docker Desktop or your existing Docker environment before continuing. If you use several Docker contexts, set FACTORY_DOCKER_CONTEXT to the one intended for this exercise. The controller will not change your default context.
Pull the exact image used by the exercise. This first step needs an internet connection; application checks use a private internal network.
docker pull ghcr.io/astral-sh/uv@sha256:531f855bda2c73cd6ef67d56b733b357cea384185b3022bd09f05e002cd144ca
With a selected context, use docker --context YOUR_CONTEXT pull ... for that pull. The pinned digest lets another reader fetch the same image instead of a moving tag.
Run the baseline
python3 factory.py check reference/b0.py --contract b0 --out runs/baseline-01
Expected result: the command exits with status 0 and prints "passed": true. Open runs/baseline-01/report.json. Every check records its name, actual result, expected result and pass state. Keep this file. A fresh output directory is required for each attempt so a rerun cannot erase your earlier evidence.
The controller starts three roles: the application, a simulated customer-record system and a test client. The application runs as an unprivileged container user. It receives its own writable state volume, read-only code and no model credentials. The test controller retains access to the simulator’s private ledger. The application does not receive that ledger’s administrator token.
The baseline has deliberately modest behavior. It validates the request, checks that fixture account A cannot update B, forwards a valid update and records a confirmed receipt. It does not yet prevent duplicate updates when the same request is retried.
Read the two sides of the write
Find ordinary_write:receipt in the report. The checker compares the application’s receipt with the receiving system’s ledger. A success response alone would let an implementation pass by inventing a receipt.
Now find lost_reply_unknown. The simulator committed the update and then closed the connection without a response. The correct application result is HTTP 202 with state: unknown. The ledger still contains the write.
| Observation | What it establishes |
|---|---|
| The receiving system rejects the request before writing | No effect occurred in this defined failure mode. |
| The receiving system records an effect and returns its receipt | The checker can match the response to that effect. |
| The connection drops after the write | The caller lacks confirmation, although the effect exists. |
These are controlled teaching conditions. A real API’s documented failure semantics may differ. You must establish those semantics before treating an HTTP error as proof that no write happened.
Check your understanding
Question: The application returns unknown. Should the user press Retry immediately?
Answer: The baseline has no duplicate protection. A retry can perform the update again. First establish whether the original operation took effect, or add an operation identity that makes retries safe. We will add that identity next.
Your evidence: Save the baseline report and write two sentences explaining which system knows that the update happened. If the run failed, keep its report and resolve the setup or application failure before continuing. A missing check is not a pass.
Continue to specifying the change.