Files
mikkeli 229d796cfd
/ crosscheck (push) Successful in 1s
Rust consumers (L4T) / Clippy, test, build, glibc for every service that compiles contracts in (push) Failing after 6s
OBD-II signals renamed obd_*, plus timing, trims, O2; GNSS signals; elm_connected; reboot command
Decision 30: CAN feeds displays, OBD-II (K-line via the ELM) calibrates, so every
obd2 signal carries the obd_ prefix and the plain names are left for decoded ones.
yukart/gnss/<signal> gives displays the fix as single values; gnss/fix stays for
navigation. Boundary: reboot beside poweroff, same guards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
2026-10-13 22:50:03 +09:00

47 lines
2.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: guidelines
---
# Contract guidelines
## 1. `signals.json` is the single source for a signal's identity
- Topic name and the envelope's `unit` are both **derived** from a registry entry.
Neither is authored by hand anywhere else.
- ⚠ **The unit appears in both the topic name and the payload, so they can
contradict each other.** Generating both from one entry is what stops that; a
hand-written `"unit"` reintroduces the failure it was meant to prevent.
- Signal names carry their unit (`gnss_speed_kph`, `obd_coolant_temp_c`), so a unit
mismatch is visible at the call site rather than one registry lookup away.
## 2. Two clocks, and they answer different questions
- `monotonic` is authoritative for **ordering and intervals**. It cannot step.
- `timestamp` is the **absolute reference** and can step: the car boots with no
network, LTE connects several minutes in, and NTP corrects the clock mid-drive.
- ⚠ **Never derive a duration from `timestamp`.** A step lands inside the interval
and the result is silently wrong, most likely during exactly the drive worth
keeping. Durations come from `monotonic`.
## 3. Raw CAN is not the envelope
- `yukart/can/raw` is binary. A four-key JSON object at 1000–3000 frames/sec is
not a reasonable encoding.
- The envelope is for decoded signals, which are low-rate by comparison.
## 4. Absent means default
- `quality` is omitted when `ok`; `mock` is omitted when false. A consumer treats
absence as the default, never as an error.
## 5. This repo is versioned by git tag
- There is no version in any topic or payload. A recorded session names the
contracts tag it was captured under, which is what keeps old captures readable.
## 6. A decoded signal's layout lives only in its registry entry
- Every `source: z27ag` signal has a `can` block in `signals.json`: frame ID, byte,
bit or length, byte order, scale and offset. The decoder reads those blocks and
nothing else, so a correction lands in one file and every consumer sees it.
- ⚠ **No CAN ID or bit position is written in any service's code.** A layout
hard-coded downstream is a second source that silently disagrees the day the
registry is corrected.
- Each block names the report with its evidence (`evidence`). A layout without
evidence is a guess and does not go in.
## 7. To be added