Protocol version field in the message contract #53

Closed
opened 2026-08-31 17:30:06 +02:00 by robert · 1 comment
robert commented 2026-08-31 17:30:06 +02:00 (Migrated from git.butzei.de)

Goal

The watchapp and the companion are installed and updated independently - you will sideload a new watchapp and forget the APK, or the reverse. Without a version field the failure mode is subtly wrong numbers rather than an honest error.

Acceptance criteria

  • Protocol version constant defined in shared/message_keys.json and generated into both sides
  • Version included in the handshake when the watchapp connects to the companion
  • Mismatch detected on both sides and surfaced as a clear message naming which side is stale
  • App degrades to a safe subset or refuses to start rather than displaying wrong values
  • Version bump rules documented: additive keys do not bump, changed semantics do
  • Mismatch path covered by tests

Files

  • shared/message_keys.json
  • watchapp/src/c/proto.c
  • companion/.../pebble/Proto.kt

Notes

Cheap now, painful to retrofit - this is why it lands in Phase 0 alongside #7 rather than later.

Update — 2026-09-02: say what a mismatch actually does

"Surfaced, not tolerated" did not say whether the app refuses to run or degrades (D46).

  • On mismatch the watchapp refuses to start a ride, and names which side is stale and which
    version each side speaks
  • No degraded or reduced mode. A bike computer showing plausible wrong numbers is worse than one
    showing none
  • Adding a key does not bump the version; changed semantics, a removed key, or a changed rate in
    PROTOCOL §4 do
## Goal The watchapp and the companion are installed and updated independently - you will sideload a new watchapp and forget the APK, or the reverse. Without a version field the failure mode is subtly wrong numbers rather than an honest error. ## Acceptance criteria - [ ] Protocol version constant defined in `shared/message_keys.json` and generated into both sides - [ ] Version included in the handshake when the watchapp connects to the companion - [ ] Mismatch detected on both sides and surfaced as a clear message naming which side is stale - [ ] App degrades to a safe subset or refuses to start rather than displaying wrong values - [ ] Version bump rules documented: additive keys do not bump, changed semantics do - [ ] Mismatch path covered by tests ## Files - `shared/message_keys.json` - `watchapp/src/c/proto.c` - `companion/.../pebble/Proto.kt` ## Notes Cheap now, painful to retrofit - this is why it lands in Phase 0 alongside #7 rather than later. ## Update — 2026-09-02: say what a mismatch actually does "Surfaced, not tolerated" did not say whether the app refuses to run or degrades (D46). - [ ] On mismatch the watchapp **refuses to start a ride**, and names which side is stale and which version each side speaks - [ ] No degraded or reduced mode. A bike computer showing plausible wrong numbers is worse than one showing none - [ ] Adding a key does not bump the version; changed semantics, a removed key, or a changed rate in PROTOCOL §4 do
Owner

Closed by PR #96 (merged): watch sends PROTO_VERSION on the reconnect edge and cold-start-already-connected case (ride_link.c) since it owns the only connection-state detection point right now (#4/#4's companion-side PebbleTransport is still a placeholder). state.c gains a pure, host-tested mismatch gate consulted at exactly the idle->running edge of ride_state_start_pause() \u2014 running/paused rides and pause/resume are unaffected even mid-mismatch, matching D46's scoped intent. carousel.c surfaces a real notice ("Watch vN / Phone vN / X is old") plus a distinct 3-pulse vibration so a refused Select doesn't read as a dead button. Companion-side ProtocolHandshake.kt is pure comparison logic (zero PebbleKit dependency), returning an exhaustive Match/Mismatch type with no degraded-mode case possible by construction. Version-bump rules were already documented (#7/D46); this PR only added a short pointer to where the runtime code landed.\n\nVerified for real on both toolchains: pebble build clean on gabbro/emery/basalt; 102/102 watchapp host tests (6 new); real ./gradlew Android/JVM builds and tests all green, XML reports confirm the new ProtocolHandshakeTest cases actually executed.

Closed by PR #96 (merged): watch sends PROTO_VERSION on the reconnect edge and cold-start-already-connected case (ride_link.c) since it owns the only connection-state detection point right now (#4/#4's companion-side PebbleTransport is still a placeholder). state.c gains a pure, host-tested mismatch gate consulted at exactly the idle->running edge of ride_state_start_pause() \u2014 running/paused rides and pause/resume are unaffected even mid-mismatch, matching D46's scoped intent. carousel.c surfaces a real notice (\"Watch vN / Phone vN / X is old\") plus a distinct 3-pulse vibration so a refused Select doesn't read as a dead button. Companion-side ProtocolHandshake.kt is pure comparison logic (zero PebbleKit dependency), returning an exhaustive Match/Mismatch type with no degraded-mode case possible by construction. Version-bump rules were already documented (#7/D46); this PR only added a short pointer to where the runtime code landed.\n\n**Verified for real on both toolchains**: pebble build clean on gabbro/emery/basalt; 102/102 watchapp host tests (6 new); real `./gradlew` Android/JVM builds and tests all green, XML reports confirm the new ProtocolHandshakeTest cases actually executed.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
robert/PedalPebble#53
No description provided.