Skip to content
Harness Engineering2026-09-116 min read

Dark Software Factories Still Need a Task Owner

Build a dark software factory around a concrete change request. Separate implementation from acceptance, preserve evidence and decide which decisions remain human.

Key takeaways

  • A coding agent can implement a change without owning the customer decision that defines success.
  • An independent effect ledger distinguishes a real update from an application that merely reports success.
  • A release decision needs both the tested artifact’s identity and evidence of its behavior.
  • Changing acceptance criteria changes the task contract and requires an explicit decision by its owner.

Rod Rivera

Author

Dark Software Factories Still Need a Task Owner

Rod's note — read with a pencil; the margins are for you.

Suppose a customer asks you to stop an integration from updating the same record twice. You give a coding agent the repository. It adds a cache, runs its tests and reports success. The code looks reasonable. Then the application restarts, the cache disappears, and the next retry repeats the update.

The missing piece was a decision about what “the same request” means and how long that identity must survive. Someone needed to specify it before anyone could judge the implementation.

That is where I would start building a dark software factory: a change whose meaning you can state, an application you can run, and evidence that can reject a plausible implementation. If you already deliver integrations, this is familiar customer work. The coding agent changes who writes the candidate; it does not settle the customer’s requirements.

What a dark software factory automates

In this series, a dark software factory is a workflow in which coding agents implement changes and automated checks decide whether a candidate can proceed. Its useful output is tested software together with enough evidence to understand the release decision.

The application being built need not contain AI. Our five-part factory workshop uses an ordinary Python contact-update service. The model helps change the service. There is no model interpreting a customer request inside the running application.

That distinction makes the exercise easier to inspect. We can ask whether a request produced one external write, whether a receipt matches that write, and whether a retry after restart repeats the effect. None of those questions needs a model to judge the answer.

The task owner defines the contract; the candidate must satisfy it

The diagram leaves a consequential decision above the automated loop: who can change the contract? Give that power to the builder without qualification, and you have given it a second way to pass. It can improve the implementation or redefine success.

Turn a request into observable behavior

For the contact-update service, the account and operation key identify one request. The email address is its payload. Repeating the same account, key and payload must return the original receipt without another external write.

Reusing the key with a different payload must return a conflict. Two accounts may use the same key independently. Concurrent identical requests must not race into several external writes. Confirmed receipts must survive an application restart.

Those are separate requirements. A cache indexed only by email could satisfy one while violating another. A process-local dictionary could appear to work until restart. A test that submits two requests sequentially cannot establish concurrent behavior.

Tempting shortcutCase that exposes it
Deduplicate by email addressTwo accounts legitimately use the same email.
Remember keys only in memoryRestart the application and repeat a confirmed request.
Return success after a timeoutInspect a dependency that may or may not have committed.
Test sequential retries onlySubmit identical requests concurrently.

Writing this table is not administrative overhead around the interesting coding work. It determines which implementations are acceptable. An agent can help you draft it, but the person who understands the receiving workflow has to judge its meaning.

The application cannot be its own receipt

Consider a dependency that writes the update and then loses the response. The caller does not know whether the effect happened. Returning a success receipt would be unjustified; returning a definite failure would also overstate the evidence.

The workshop preserves an unknown result. A later change adds lookup-based reconciliation. The application asks the receiving system whether the operation exists and only confirms it when the returned evidence matches.

A committed update and a missing reply can coexist

The checker reads a separate effect ledger. This matters because a candidate could return a beautifully formatted success response without making any update at all. It could also perform the update twice while returning the same receipt twice. Response checking and effect checking answer different questions.

The simulator’s contract is deliberately narrow

The exercise defines one HTTP failure as occurring before any write. That is a property of this simulator. Do not transfer the assumption to an arbitrary production API without establishing its documented and observed behavior.

The evaluation environment therefore belongs in the design from the beginning. It determines what the factory can know about the candidate, including which failures remain invisible.

Keep the released artifact tied to the test

A test result applies to a particular candidate. If the agent makes one more cleanup edit afterward, the previous result does not identify the new file.

Our controller freezes the source and records its hash. After acceptance, it runs those same bytes in fresh disposable containers and repeats the checks. The hash establishes identity. The observations establish selected behavior. Neither is a substitute for the other.

This is a local teaching release. It does not establish a production rollout, a 24-hour reliability result or coordination between several application replicas. The workshop makes those limits explicit because a small example becomes misleading when its claims expand faster than its evidence.

Quick check — An agent proposes deleting the restart check because the service normally stays running. What kind of change is this?

Build the small loop before expanding its authority

Establish the starting behavior

Run the baseline against its own contract. Then show that it fails the new duplicate-request contract. Keep both reports so the required difference is visible.

Generate one candidate

Ask for the specified implementation change. Retain the model response, the candidate and failed attempts. Record the time you spend reviewing or repairing them.

Check before releasing

Run the unchanged acceptance contract against the frozen candidate. Only an accepted artifact proceeds to the fresh exercise environment, where the checks run again.

Before opening the answer, consider this variation: the API returns the correct receipt, but its ledger contains two identical writes. Is the release acceptable?

Then deliberately supply a faulty implementation. If the checker lets it through, repair the checking machinery before using it to judge more ambitious work. This is a test of the factory’s decision, not a failure to hide from the build statistics.

The next question is whether this process reduces your total work. Count specification, review, failed runs and recovery, not only generation time. The cost of unverified output is often paid after the code has already looked finished.

If you have not yet used a coding agent on a bounded task, the Claude Code for Business course offers a practical entrance before you attempt the factory workflow.

You do not need a fully autonomous organization to investigate any of this. You need a concrete change, a bounded execution environment and someone who owns the acceptance decision. Start with the runnable workshop, then expand the workflow only when the evidence supports the next responsibility.

Build the factory on a small application

Run the baseline, specify one change and inspect the acceptance evidence in the five-part workshop.

Ready to put an agent to work?

Join the Prof Rod newsletter for one educational lesson a week, with worked examples attached. It is free to register for and separate from the Zero Employee community.