# 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 channel enumerate --format=json` and filter for the requested CAN
   or LIN capability. Mixed XL4 devices expose both kinds of fixed-function
   ports under the same model name.
3. Compare serial, port, model, firmware, and capability with cached values.
4. For CAN, 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. For LIN, confirm the physical master/slave topology, role, bitrate, pull-up,
   and 12 V supply direction from the LDF/matrix and bench wiring. Enumeration
   identifies LIN-capable ports but cannot discover which endpoints are wired
   together or which node may safely source the bus supply.
6. Confirm the detected or supplied timing against the ECU/network specification
   when one is available.
7. 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.
8. Validate that each DBC or LDF/matrix source exists and matches the ECU/network
   variant. BMCLI does not currently parse LDF files.
9. Persist confirmed CAN/UDS 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. Until runtime help adds LIN profile
   fields, keep explicit LIN context in the generated harness configuration
   rather than inventing `.bmcli` schema members.

## 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.
