Milestone 4 of 8

Record one failed run honestly

Use the supplied failure adapter to preserve configuration and stable failure evidence without inventing unavailable results.

A failure is evidence too. Record enough to understand where the run stopped, without creating a result that was never produced.

Goal

Run the supplied failure adapter through the same interface, preserve its configuration and status evidence, and represent the unavailable result honestly.

Inputs

Use tests/failing_experiment.py, which exposes the same run_experiment(config, readings) shape and raises the documented exception. Use a valid configuration and the same source identity used for a completed run. Do not make the normal computation fail by changing the source data.

The failed run owns runs/<run_name>/. Its status must identify failed, a stable failure stage, and a short error message. It must not pretend that a result, values file, or figure exists when the adapter stopped before creating one.

Deliverables

Extend src/runner.py so a supplied computation failure produces explicit failure evidence. Save the configuration, source identity, status, and any artifact inventory that is true at the time of failure. Update report.md with the failure stage and the files that are unavailable.

Keep unexpected filesystem failures distinct from the supplied computation failure. The project does not promise a status file when its own status location is unwritable, but it must not turn such a failure into completed.

Checks

Check that the failure adapter is called through the same interface and that the status is failed, not completed. The recorded stage and error message must be stable and short enough to read. Check that no plausible result.json, values.csv, or figure.png is created after the computation raises.

Check that the failed configuration remains visible and that a later completed run with a different name does not overwrite it. Test the public failure case and an unexpected write failure separately; do not confuse the two.

Workspace

Keep failure handling in src/runner.py and use the same runs/ layout as a completed run. src/main.py should make the selected adapter visible rather than hiding it behind a global flag. Keep the read-only failure fixture unchanged.

Hints

HintUnavailable is a value
A failed run can have a saved configuration and no result. Represent missing result artifacts explicitly instead of filling them with null-looking success data.
HintName the boundary where it stopped
Use one stable stage such as experiment or result_write, then keep the exception message short and factual.

Review

Inspect the failed directory and compare it with a completed directory. Explain why a failure record is more useful than a fabricated zero, empty plot, or partial result marked as complete.

How to check your work

Checks compare the failure status and artifact inventory with the supplied fixture. The supplied fixture preserves the failure; it does not hide it so that the run list looks cleaner.