# Troubleshooting

## Toolchain

### `hil-cli doctor` reports a failure

* **hil-orchestrator not found** — build it first: `go build -o
  ../bin/hil-orchestrator.exe .` inside `firmware/`, or set
  `HIL_ORCHESTRATOR` to its path.
* **CRUMB not found** — set `HIL_CRUMB_DIR` to the directory containing
  `CRUMBWPF.exe`.
* **Node wrapper not found** — the check looks relative to the repo root;
  running `doctor` from inside a project still works because it also checks
  the binary's own location.

## Serial / hardware

### No COM port, or the node isn't attached

Use the headless path — it is the fully-supported way to run scripts without
hardware:

```powershell
hil-cli simulate src/main.hil
```

Or start the monitor with `-port none` / `hil-cli run` with `HIL_PORT=none`.

### "Monitor not running on port 9000"

`hil-cli send` / `hil-cli flash` / `hil-cli stop` talk to a running monitor via
TCP. Start the monitor first (`hil-cli run`, or `hil-orchestrator -port <p>`)
in another terminal.

### Watch out for the real serial ports

COM1 and COM3 (Intel AMT SOL) are real ports on this machine. Do **not** write
to them — always prefer `-port none` or your own device port.

## CRUMB

### Generated circuit opens but the Nano does nothing

* Press the **RUN** button in CRUMB.
* Confirm the serial monitor is open (baud 9600).
* Check the serial output for error messages (e.g., DHT checksum failures).
* An infinite `WHILE` with no `DELAY` still executes (the simulator steps the
  interpreter per frame) but will spin; add `(DELAY ...)` inside loops.
* Buzzer not sounding? Ensure you're using a **passive buzzer** on pin D11.
  Active buzzers just set the pin HIGH silently — `tone()` only works with
  passive buzzers.

### `--strict` fails

The script uses an op that produces a warning. Either remove the op or drop
`--strict` (the op generates a warning at runtime).

### CRUMB can't find the simulator

`hil-cli crumb` looks in `--crumb-dir`, then `HIL_CRUMB_DIR`, then the default
dev path. Export `HIL_CRUMB_DIR`.

### Generated C has hyphens in identifiers

HIL LISP names with hyphens are automatically converted to underscores in C.
`DUAL-BLINK` becomes `DUAL_BLINK`. This is expected — the transpiler handles
name sanitization via `cIdent()`.

### Division by zero in MAP

MAP with degenerate ranges (`inMax == inMin`) is guarded in both host and
transpiler. The result is 0 (or `outMin` for the host).

### UTF-8 BOM errors

HIL scripts must be UTF-8 without BOM. Re-save in your editor as UTF-8 (not
"UTF-8 with BOM"). The transpiler strips BOM from `.hil` files automatically.

## Language

### `Unknown symbol "x" in expression`

`SET x ...` before using `x`, or check case (variables are case-sensitive).

### `INCLUDE cycle detected`

An `(INCLUDE "file")` chain loops back on itself. Check the include graph.

### Garbled characters in LOG output

HIL scripts must be saved as UTF-8. Files encoded with legacy code pages
(common for Windows Notepad "ANSI") produce replacement characters in the CRUMB
sketch. Re-save as UTF-8.

### Delays > 127 ms in autopilot

Fixed — the monitor records `A W 68 0 0` + `A D <ms> 0 0` and the firmware
sleeps `val1` ms. If your node firmware is older than this fix, rebuild it.

## Node wrapper

### `Timeout waiting for HIL engine on port X`

The monitor did not report `ready` in 10 s. With `-port auto` and no device,
the scan never connects — use `connect('none', 9600)`.

### Script runs but no `idle` event

`idle` fires on `execution_complete`. If the script hangs (infinite loop with
no `DELAY`, or a `WHILE` that never exits), it never completes — the monitor
does not time out scripts.
