Skip to content

docs(vehicle): document BLE timeout verification contract#56

Merged
Bre77 merged 3 commits into
mainfrom
fm/tfa-ble-verify-contract-k2
Jul 9, 2026
Merged

docs(vehicle): document BLE timeout verification contract#56
Bre77 merged 3 commits into
mainfrom
fm/tfa-ble-verify-contract-k2

Conversation

@Bre77

@Bre77 Bre77 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Intent

  • Issue: BLE mutating commands (RKE/closure actions, wake_up()) can raise BluetoothTimeout even though the command executed on the vehicle - live BLE testing confirmed door_unlock/door_lock and wake_up() timing out while a follow-up state read showed the command had taken effect.
    • A caller that treats that timeout as failure is wrong, and one that blind-retries on it double-executes non-idempotent commands.
  • Fix: documentation-only, scoped as a contract, not a redesign.
    • Added a docstring to VehicleBluetooth stating the contract: a BluetoothTimeout from a mutating command is inconclusive; callers must snapshot -> act -> verify-by-state, and must never blind-retry a non-idempotent command on timeout.
    • Added a docstring to Commands._command documenting that its own WAIT/fault retry can re-send an already-executed, non-idempotent command.
    • Corrected a stale AGENTS.md/CLAUDE.md note that claimed "a write timeout means the write never landed" - disproven by live testing - and rewrote it to the inconclusive/verify-by-state contract, plus added a new bullet on the retry double-execution window.
  • Scope boundaries (deliberately not done here):
    • No behavior changes, no new retry logic, no defensive machinery.
    • bluetooth.py's _send/connect internals left untouched beyond the class docstring - a parallel effort is wrapping transport exceptions there, and touching more would create rebase conflicts.
  • Verification: ruff check, ruff format --check on touched files, pyright strict (0 errors), and the full pytest suite (153 passed) - all clean.

What Changed

  • Documented the VehicleBluetooth BLE mutating-command contract: BluetoothTimeout is inconclusive, so callers should verify actuation from follow-up vehicle state instead of treating it as definitive failure.
  • Added internal command-path documentation noting that signed-command retries after WAIT or token/epoch faults can resend the same non-idempotent command.
  • Updated BLE and signed-command docs to align timeout and retry guidance with the verify-by-state contract.

Risk Assessment

✅ Low: The change is documentation-only, narrowly scoped to clarifying BLE timeout and retry semantics, and I found no introduced correctness or API-contract risks.

Testing

Inspected the documentation-only diff, exercised BLE mutating command paths and the full suite, and produced runtime evidence showing the new developer-facing contract plus the WAIT retry double-send behavior; all tests passed and no working-tree artifacts remain.

Evidence: BLE verify contract evidence

Runtime evidence extracts the new VehicleBluetooth and Commands._command docstrings and demonstrates WAIT-then-OK on mocked BLE door_lock produces two _send calls with RKE_ACTION_LOCK both times.

## VehicleBluetooth class docstring
  Class describing the Tesla Fleet API vehicle endpoints and commands for a specific vehicle with command signing.

  A ``BluetoothTimeout`` raised by a *mutating* command (RKE/closure
  actions, HVAC/media/charging commands, ``wake_up``) is inconclusive, not
  a failure - the vehicle can execute the command without its ack reaching
  the client. Callers must snapshot state before acting and verify the
  outcome with a follow-up state read after any timeout, and must never
  blind-retry a non-idempotent command (toggles, volume steps, schedule
  add/remove) on a timeout alone. The inherited WAIT/fault retry
  (``Commands._command``) can also re-send an already-executed command.

## Commands._command docstring
  Serialize a message and send to the signed command endpoint.

  On a WAIT status or an epoch/token fault, this re-signs and re-sends
  the identical command (bounded at 3 attempts) - for a non-idempotent
  command that window can apply it twice if the first attempt actually
  executed despite the WAIT/fault reply.

## Runtime command result
  {'response': {'result': True, 'reason': ''}}

## Physical _send calls observed
  2

## Decrypted commands sent on the wire
  RKE_ACTION_LOCK
  RKE_ACTION_LOCK
Full narrative / original brief

Document and enforce a verify-actuation-by-state contract for BLE mutating commands in tesla_fleet_api. Live BLE testing (not part of this diff) proved that door_unlock/door_lock and wake_up() can raise BluetoothTimeout while the command actually executed on the vehicle - so a caller treating that timeout as failure is wrong, and blind-retrying on it double-executes non-idempotent commands. This PR is documentation-only by design (explicitly scoped as contract, not a redesign): (1) added a docstring to the VehicleBluetooth class stating the contract - a BluetoothTimeout from a mutating command is inconclusive, callers must snapshot->act->verify-by-state, and must never blind-retry a non-idempotent command on timeout; (2) added a docstring to Commands._command documenting that its own WAIT/fault retry can double-execute a non-idempotent command; (3) corrected a stale AGENTS.md/CLAUDE.md note that previously claimed 'a write timeout means the write never landed' - that claim is disproven by the live evidence, so the bullet was rewritten to the corrected inconclusive/verify-by-state contract, and a new bullet was added documenting the retry double-execution window. No behavior changes, no new retry logic, no defensive machinery were added - deliberately out of scope. Also deliberately left tesla_fleet_api/tesla/vehicle/bluetooth.py's _send/connect internals untouched beyond the class docstring, since a parallel effort is wrapping transport exceptions there and touching more would create rebase conflicts. Verified with ruff check, ruff format --check on the touched files, pyright strict (0 errors), and the full pytest suite (153 passed) - all clean.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed ✅
  • ⚠️ tesla_fleet_api/tesla/vehicle/bluetooth.py:185 - The new public class docstring sends readers to AGENTS.md for the evidence behind the BLE timeout contract, but the wheel only packages tesla_fleet_api* plus py.typed, so installed users reading help(VehicleBluetooth) or generated API docs get an internal, unshipped reference. Since this PR is documenting a user-facing safety contract, consider keeping the rationale self-contained here or pointing at shipped/repository documentation instead.

🔧 Fix: Remove internal doc references
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Inspected changed files with git diff --unified=80 629c16d8123211a64c2cd31f68b3866e29e4d6c6..e36797e3f618d46c02c38cf06174b6c4db468445 -- AGENTS.md tesla_fleet_api/tesla/vehicle/bluetooth.py tesla_fleet_api/tesla/vehicle/commands.py.
  • Ran BLE-focused command-path tests: uv run pytest tests/test_ble_mocked_commands.py tests/test_ble_mocked_closures_locks.py tests/test_ble_mocked_media_commands.py tests/test_ble_charging_commands.py tests/test_ble_climate_commands.py tests/test_ble_send_transport.py.
  • Ran full regression suite: uv run pytest tests.
  • Generated reviewer evidence with PYTHONPATH=tests uv run python - <<'PY' > /tmp/no-mistakes-evidence/01KX4DTJXFBCSN1NWT310F0YC0/ble_verify_contract_evidence.txt, extracting runtime docstrings and demonstrating WAIT retry behavior over mocked BLE transport.
  • Removed transient working-tree caches with find . -name '__pycache__' -type d -prune -exec rm -rf {} + && rm -rf .pytest_cache.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

firstmate crewmate added 3 commits July 10, 2026 08:39
Live testing proved door_unlock/door_lock both raised BluetoothTimeout
while physically executing, disproving the prior "timeout means the
write never landed" note. Document the corrected contract on
VehicleBluetooth and Commands._command: a mutating-command timeout is
inconclusive, and the library's own WAIT/fault retry can double-apply
a non-idempotent command.
@Bre77
Bre77 force-pushed the fm/tfa-ble-verify-contract-k2 branch from 933fe39 to 5c6a51c Compare July 9, 2026 22:40
@Bre77
Bre77 merged commit 2300b74 into main Jul 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant