Files
contracts/docs/GUIDELINES.md
T
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

2.3 KiB
Raw Blame History

type
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