Step3Simulation mounted with a simulation id and immediately called
doStartSimulation() with force: true. Because the id lives in the route
path (/simulation/:simulationId/start), a browser refresh remounted the
component and re-sent that request, so the backend stopped the running
subprocess and cleaned the run directory: run_state.json, the twitter and
reddit actions.jsonl action logs, and both *_simulation.db files. The
timeline, posts and comments views read those files directly, so the data
was unrecoverable.
Probe the run status before deciding what to do. A simulation that has
never run (runner_status "idle" with no recorded actions) still starts
exactly as before. Anything else is adopted instead of restarted: live
runs resume polling, finished runs load their existing timeline read-only.
If the status probe itself fails we now do nothing rather than risk
overwriting a run we could not verify.
force is also no longer hardcoded to true. The remaining call site only
runs when there is nothing to lose, and the flag should never be an
implicit default.