# Architecture

## Runtime split

### Host controller — Python on RPi/PC

Responsibilities:
- operator workflow and manual-mode UI integration;
- state machine orchestration;
- controller-job intake validation;
- geometry gate;
- setpoint command stream;
- telemetry capture;
- logs, manifests, hashes, status file;
- slow watchdogs and data export.

### Teensy firmware — C++ on Teensy 4.x

Responsibilities:
- inner loop around ~1 kHz;
- KWR75B-CAN F/T receive path;
- encoder acquisition;
- force PID output;
- table/spindle/actuator command outputs;
- fast safety checks;
- heartbeat supervision;
- telemetry frames at >=100 Hz;
- ACK/NACK and event/fault frames.

## State machine

Current accepted state names:

```text
IDLE
JOB_LOADED
READY
RUNNING
PAUSED
ABORTING
COMPLETED
ABORTED
FAULTED
MANUAL
```

Important rules:
- `FAULTED` exits only through explicit operator reset.
- `JOB_LOADED -> READY` requires operator acknowledge.
- `IDLE -> MANUAL` is allowed only with no job loaded.
- Illegal transitions are errors and events, never silent ignores.
- Manual mode uses the same safety/interlocks as job mode.

## Manual mode sequence

1. Machine starts in `IDLE`.
2. Operator opens Manual Mode.
3. Host enforces the geometric gate.
4. Host sends `MANUAL_START` to Teensy.
5. Teensy ACKs or NACKs with a machine-readable reason.
6. Host sends live `SETPOINT` updates.
7. Teensy emits telemetry and events.
8. Operator stops; host sends `MANUAL_STOP`.
9. Host writes manual-session log and artifacts.
