This file is the **first prompt/context file** to give to Cédric's LLM or coding assistant when working in this repository.
It condenses the approved technical direction for `polisher-control` into one implementation-oriented context pack. It is an aid for coding and design discussions, not the authority itself.
If this file conflicts with the source specs or with Antoine's explicit direction, stop and ask Antoine before changing architecture, telemetry contracts, safety behavior, or v1 scope.
## Scope / non-scope
### In scope for `polisher-control`
`polisher-control` is the machine-side execution layer. It owns:
- Teensy firmware and hard-real-time loop.
- Raspberry Pi / host controller and touchscreen/manual workflow.
- Host ↔ Teensy protocol.
- Force setpoint execution and closed-loop Fz control.
- Table/spindle/arm-drive command interfaces.
- KWR75B-CAN force/torque acquisition.
- ODrive S1 + M8325s spindle integration.
- State machine, pause/resume/abort, faults, alarms, interlocks.
- Telemetry, event logs, manual-session logs, run artifacts, and `/data/` layout.
- Conservative machine capability descriptor.
### Explicitly out of scope
Do **not** implement or infer:
- Optical figuring strategy.
- Interferometer/metrology interpretation.
- Dwell-map optimization or pass planning.
- Preston coefficient calibration or learning logic.
- Autonomous correction decisions.
- Controller-side replanning.
- Silent mutation of upstream setpoints.
- Remote control of the machine without a physically present operator.
Core rule: **the controller executes approved setpoints safely; it does not decide polishing strategy.**
## Source references
Use repo docs first for implementation, then the source specs if there is ambiguity.
### Repo implementation docs
-`README.md` — repository overview and v1 finish line.
run logs + manual telemetry return upstream for analysis and calibration
```
### `polisher-sim`
Owns the question: **what should be done next?**
It may ingest interferometer maps, model removal, plan passes, estimate uncertainty, calibrate machine-specific behavior, and produce frozen job packages. It must not drive hardware directly.
### `polisher-post`
Owns the question: **how do we express the approved plan safely for this machine?**
It validates schemas, checks machine capabilities, normalizes units, records translation losses, and emits controller-safe `controller-job.v1` packages.
### `polisher-control`
Owns the question: **how do we execute these approved setpoints safely now?**
It runs the machine, enforces safety, records exact reality, and exports artifacts. It must be boring, predictable, auditable, and conservative.
## v1 finish line
The v1 finish line is:
> Normand can operate the polisher manually from the touchscreen, producing clean synchronized telemetry, with safety enforced.
Program execution exists as a contract scaffold and future path, but the v1 production surface is manual operation.
### v1 priority order
1. Safety/interlocks and deterministic state machine.
2. Manual mode from touchscreen / host UI.
3. Stable host ↔ Teensy setpoint and telemetry protocol.
4. KWR75B-CAN force/torque acquisition and stale-frame detection.
5. Table/arm encoder acquisition and synchronized timestamps.
-`ARM_HANDLING_INTERLOCK` if final lock/cam-nut feedback exists.
## Force control and tool handling
- Force PID closes on the compensated contact force path.
- Store `fz_tool_weight_offset_n` for the installed tool/head configuration.
- Keep raw force available for diagnostics as `fz_raw_n` where practical.
- Compute compensated contact force as:
```text
fz_contact_n = fz_raw_n - fz_tool_weight_offset_n
```
- If only one canonical force channel is emitted, document that `fz_n` means compensated contact force and include the offset in session/run metadata.
- Do not implement a powered Zero-G state in v1.
Mechanical safe tool-removal workflow:
1. Stop active manual/job operation.
2. Command force to zero and stop table, spindle, and arm drive.
3. Confirm compensated force is near zero.
4. Confirm machine is in `IDLE` or stopped manual condition.
5. Engage/verify swing arm or arc mechanical lock.
6. Remove cam arm nut to free arm rotation.
7. Move arm aside by hand.
8. Remove tool from blank by hand.
9. Reinstall/seat tool, restore mechanical configuration, and rerun the geometric gate before software-controlled motion.
## Run artifacts and data layout
Write run data to USB SSD, not the RPi SD card.
Baseline layout:
```text
/data/
├── runs/
│ └── run-*/
│ ├── run-log.v1.json
│ ├── telemetry.csv
│ ├── telemetry-derived.parquet
│ ├── segment-stats.json
│ ├── dwell-map.npz
│ ├── work-map.npz
│ ├── anomaly-windows/
│ └── manifest.json
├── manual/
│ └── manual-*/
│ ├── manual-session-log.v1.json
│ ├── telemetry.csv
│ ├── telemetry-derived.parquet
│ ├── segment-stats.json
│ ├── dwell-map.npz
│ ├── work-map.npz
│ └── manifest.json
├── capabilities/
│ └── machine-capabilities.v1.json
└── status.json
```
For v1 hardware proving, raw full-rate telemetry, run/manual logs, stable filenames, and hashes are mandatory. Derived artifacts may begin as a simple post-run routine but should follow the contract from the start.
## Feature request workflow for Antoine/Cédric
When Antoine says he wants to add a feature to `polisher-control`, classify it before coding:
1.**Execution feature** — belongs here if it changes host state machine, protocol, firmware, manual workflow, telemetry, safety, or run artifacts.
2.**Contract feature** — may require parallel changes in `shared/schemas`, `polisher-post`, and possibly `polisher-sim`.
3.**Planning/intelligence feature** — probably belongs upstream in `polisher-sim` or `polisher-post`, not here.
4.**Safety/scope feature** — requires Antoine approval before implementation if it changes interlocks, limits, fault behavior, telemetry schema, protocol semantics, or v1 scope.