--- title: Feature Intake — Toolhead Spindle Direction Selection status: draft requested_by: Antoine Letarte / Normand Fullum generated_by: Nick / Hermes project: P11-Polisher-Fullum repo: polisher-control source_truth: false created: 2026-06-02 privacy: technical-only --- # Feature Intake — Toolhead Spindle Direction Selection ## 1. Requested behavior Normand wants the operator to select the toolhead/tool spindle rotation direction between clockwise and counter-clockwise. The operator-facing control belongs in manual mode first, and the same field should be carried in future controller-job segments so program execution does not require a protocol/schema redesign. ## 2. Classification - [x] Execution feature in `polisher-control` - [x] Contract feature touching schemas/protocol/telemetry/logs - [ ] Planning/intelligence feature that belongs upstream - [ ] Safety/scope feature requiring Antoine approval beyond this explicit request Rationale: the controller is not deciding polishing strategy. It is executing/logging an operator- or job-selected spindle direction. Because this changes the host↔Teensy payload and controller-job/log shape, it is also a contract feature. ## 3. Operator-visible behavior - Manual UI exposes a spindle direction selector next to spindle RPM. - Allowed values are: - `cw` — clockwise - `ccw` — counter-clockwise - Physical convention: direction is viewed from above the toolhead looking down toward the mirror/tool contact. - Default for existing/manual startup can be `cw` unless Antoine/Cédric chooses another default. - Any direction change while running is logged as a timestamped setpoint event. ## 4. Affected layers - Host controller: normalize/validate direction aliases and include direction in manual setpoints/log events. - Teensy firmware: accept direction in `MANUAL_START`, `SETPOINT`, and future `SEGMENT_START`; map to ODrive command sign. - Host ↔ Teensy protocol: add `spindle_direction` / `commanded_spindle_direction` enum values `cw` / `ccw`. - Telemetry channels: add `spindle_direction_setpoint` and `spindle_direction_actual` as recommended channels. - Run/manual-session logs: record direction separately from RPM; RPM remains a non-negative magnitude. - Machine capability profile: advertise `supported_spindle_directions: ["cw", "ccw"]`. - Shared schemas: add direction fields to job/controller-job/run-log contracts. - Tests: assert stable enum values, schema fields, and telemetry channel presence. ## 5. Safety implications - Direction must not be inferred from signed RPM; use explicit enum plus non-negative RPM magnitude. - Direction reversal while spindle is moving should be ramped/handled safely by firmware/ODrive implementation. The scaffold currently defines the contract; Cédric should decide whether live reversal is allowed directly or requires ramp-to-zero before applying the new direction. - ODrive sign mapping is a commissioning item: firmware must be configured so UI `cw`/`ccw` matches physical observed tool rotation. Safety decision: - [x] No new optical strategy or autonomous behavior. - [x] Implementation should add a safe reversal rule before hardware use. ## 6. Contract implications - New controller-job segment field: `commanded_spindle_direction` enum `cw|ccw`. - New planning job pass field: `spindle_direction` enum `cw|ccw`. - New run-log commanded fields: `spindle_direction`. - New capability field: `supported_spindle_directions`. - New telemetry context channels: `spindle_direction_setpoint`, `spindle_direction_actual`. ## 7. Acceptance checks - [x] Host contract tests for enum values and alias normalization. - [x] Schema field test for `commanded_spindle_direction`. - [x] Telemetry channel test for direction channels. - [ ] Firmware compile/build check once Cédric maps this into Teensy/ODrive code. - [ ] Bench test confirms UI `cw` physically rotates clockwise by the documented convention. - [ ] Bench test confirms UI `ccw` physically rotates counter-clockwise by the documented convention. - [ ] Bench test confirms live reversal behavior is safe or blocked until spindle reaches zero. ## 8. Open questions - Cédric: confirm the ODrive command/sign mapping and whether live direction reversal requires ramp-to-zero. - Antoine/Normand: confirm the physical viewing convention: current draft uses “viewed from above the toolhead looking down toward the mirror/tool contact.” ## 9. Implementation notes Initial scaffold update created on branch `docs/nick-llm-context-20260602`: - `host/polisher_control/contracts.py` - `host/polisher_control/telemetry_channels.py` - `tests/test_spindle_direction_contract.py` - `shared/schemas/*.schema.json` - `shared/schemas/examples/*.json` - `shared/machine/fullum-alpha.capabilities.v1.json` - affected docs/checklists