# Bench Environment

Use stable `SN/port` identifiers in every persisted bench profile and generated
script. A numeric enumeration index is allowed only after inspecting the current
enumeration result and must not be carried across hosts or USB topology changes.

On Linux, `bmcli doctor` distinguishes BMAPI enumeration failure from a visible
BUSMUST USB device that lacks `/dev/bus/usb` permissions. Follow its bundled
udev-rule instruction instead of running long-term automation as root.

## State model

| State | Meaning | Action |
|---|---|---|
| `READY` | Hardware identity, port, bus timing, and operation-specific values are validated | Execute the requested workflow |
| `DEGRADED` | Optional data such as DBC is unavailable | Continue with raw IDs/payloads and record the limitation |
| `NEEDS_INPUT` | A required logical value has no safe discovery path | Ask for the smallest missing set |
| `DISCOVERY_REQUIRED` | Cached physical values are missing or stale and discovery is authorized | Enumerate, AutoSet, validate, then persist |
| `OFFLINE` | No suitable hardware or active bus is reachable | Generate scripts/tests/docs without claiming execution |

## Configuration ownership

Use two files so portable ECU intent is not mixed with one engineer's USB setup.

`.bmcli/ecu.json` is project-owned and may be versioned:

```json
{
  "schema_version": 1,
  "ecu": {
    "name": "body-controller",
    "variant": "production-a"
  },
  "can": {
    "mode": "normal",
    "nbitrate_kbps": 500,
    "dbitrate_kbps": 2000,
    "terminal_resistor": "120"
  },
  "uds": {
    "request_id": "0x7E0",
    "response_id": "0x7E8",
    "addressing": "normal-11bit",
    "padding": "0x00"
  },
  "dbc": ["network/body-controller.dbc"]
}
```

`.bmcli/bench.local.json` is machine-owned and must be gitignored:

```json
{
  "schema_version": 1,
  "analyzer": {
    "channel": "10356/1",
    "model": "BM-CANFD-X4",
    "firmware": "1.2.3.4"
  },
  "validated": {
    "method": "enumerate+autoset"
  },
  "local_paths": {
    "security_algorithm": "C:/ecu/oem/security.dll"
  }
}
```

Add `.bmcli/bench.local.json` and generated captures containing customer data to
the project's ignore rules. Do not put secrets, seed-key material, or proprietary
firmware into the project configuration.

## Initialization sequence

1. Run `bmcli doctor`.
2. Run `bmcli device enumerate --format=json` and filter for CAN capability.
3. Compare serial, port, model, firmware, and capability with cached values.
4. If the channel is unknown and discovery is authorized, run passive AutoSet on
   plausible ports one at a time. Stop when one succeeds only if the topology is
   unambiguous. If the bus is silent, offer active AutoSet; explain that it sends
   probe frames and require explicit authorization before running it.
5. Confirm the detected timing against the ECU/network specification when one is
   available.
6. Validate UDS IDs with `uds discover` using TesterPresent or a documented read
   DID. Dry-run first, require `--allow-functional`, and never auto-select one of
   multiple correlated responders. When `selection_required=true`, show the
   candidate response IDs and ask the user to choose. Treat inferred physical
   request IDs as candidates until an ECU identity read confirms the target.
7. Validate that each DBC path exists and matches the ECU/network variant.
8. Persist confirmed logical and physical values with `bmcli bench init`, then
   run `bmcli bench validate --hardware --format=json`. Do not hand-edit the
   files when the CLI exposes the field.

## Stale configuration triggers

Re-enter initialization when any of these occurs:

- configured serial/port is absent from enumeration;
- model, firmware, or capability changes unexpectedly;
- AutoSet no longer sees the configured bus timing;
- repeated transport timeouts occur after USB and bus checks;
- UDS responses come from an unexpected ID or ECU identity DID changes;
- the user says the analyzer, port, harness, ECU, vehicle, or DBC changed.

Invalidate only the affected layer. A changed USB port does not invalidate the
logical UDS specification; a changed ECU variant may invalidate UDS IDs and DBC
while leaving the analyzer identity valid.
