# State machine

Open `index.html`. Choose **Upload file**, **Interrupt upload**, then **Try again**. The upload is a local simulation; no file leaves the browser.

The state map follows the preview. Buttons beside it let you try other events; unavailable actions are disabled. Turn off **Advance automatically** to inspect a state at your own pace.

## Try the failure paths

- **Cancel, then send an old response.** It must stay cancelled.
- **Fail, go offline, then retry.** Retry stays unavailable until you restore the connection.
- **Pause, then resume.** Progress stays in place, but responses from the earlier attempt no longer count.

## Reuse it

`machine.js` contains the transition table and pure `transition(state, event)` function. `app.js` handles timers, rendering and controls. Open **Implementation** to inspect the activity log, copy the machine or export a trace.

The sample includes the complete source. The full library adds Async UI states, Component contracts, Status announcements and Integration contract tests. The gallery lists which skills are available in your edition and builds a project brief from the example.

For a real upload, replace the timer with your service. Keep effects outside the reducer. Pass the current attempt ID with progress, failure and completion events so cancelled work cannot change a newer request. Only offer pause/resume if the service can preserve progress.

## Replay an exported trace

The version 2 trace contains the last 200 submitted events, including `PROGRESS` and ignored events. Its `initial` checkpoint is the state immediately before those retained events. With `machine.js` loaded, replay them in order:

```js
const replayed = trace.events.reduce(
  (state, event) => WorkshopMachine.transition(state, event.input),
  trace.initial,
);
```

The result should equal the exported `state`. This reproduces state changes, not timer timing or real network traffic. The visible activity log shows only the latest 20 non-progress events. **Implementation → Reset** starts a fresh trace.

## Check your adaptation

- Invalid actions and stale responses leave state unchanged.
- Offline start, resume and retry stay blocked.
- Progress stays within 0–100 and never moves backwards within an attempt.
- Completion requires 100% progress and the current attempt ID.
- Reset invalidates older work; navigation clears the simulation timer.

Reference: [State transitions and guards](https://stately.ai/docs/transitions).
