docs(protocol): document the COMMAND_RESPONSE body (#894, #891) - #915
Merged
Conversation
PROTOCOL.md documented the envelope down to `payload [11..]` and stopped, so the two bytes every reply actually opens with were described nowhere — even though #899 made both decoders publish them and added CommandResult to the schema. Three places had been describing the same layout ad hoc instead: DeviceConfigReadProbe and FeatureFlagProbe each say "the 2-byte response header (pay[1] is the 5/MG result code)" in their own comments, and the ECG paragraph mentions a result code in passing. New §2.4 states it once, for both families: resp_cmd/resp_seq/result at [6][7][8] on 4.0 and the same +4 on 5/MG. It also records that resp_seq is the strap's counter rather than the echoed host-assigned envelope seq — a real capture shows envelope seq 147 beside resp_seq 2, and the repeated-resp_seq signature is what identified a duplicated write in #791. The part worth writing down is the first BODY byte. GET_BATTERY_LEVEL puts the charge percentage there (47 in the hardware-confirmed fixture), so the slot carries real data, but on every other captured command it has only ever been 1. For the wrist and ECG toggles what that means is open: sending SELECT_WRIST with argument 0 got 1 back, which refutes an echo of the request, but every frame captured so far had a stored value of 1, so "reads back stored state" and "this handler writes a literal 1" predict identically on all of them. Documented as open, with what would settle it, rather than resolved — the decoder deliberately leaves the byte unnamed and this explains why to the next reader. Old §2.4 Checksums and §2.5 Reassembly shift to §2.5/§2.6. No cross-reference in the tree points at either; the only internal PROTOCOL.md section reference is §2.2, unchanged. Every claim checked against source before writing: both platforms' offsets from the decoders, the PENDING-then-SUCCESS and UNSUPPORTED(3)-on-haptics results from the captures that produced them, and the body-byte table recomputed from the committed fixtures.
ryanbr
added a commit
that referenced
this pull request
Jul 28, 2026
Cutting 9.2.1 left main failing the i18n gate. appchangelog-gen.py writes the
Android title as a raw Kotlin literal:
title = "{esc_kt(wn["title"])}", # appchangelog-gen.py:60
so every release adds one hardcoded UI string, which is exactly what #878
described. That issue is closed, but the generator was never changed — 9.2.0's
title was localised by hand in #886 and the issue closed on the strength of it.
Same thing here, so the same manual fix, and #878 reopened for the generator.
Two things made it worse than a normal red check. The release workflow pushes
with GITHUB_TOKEN, and GitHub does not trigger workflows on those pushes, so no
run exists on 7054aef or 21e36a2 — main was red with nothing reporting it. And
the audit is a whole-tree gate rather than a diff, so it red-checks every open PR
on a line none of them touched; #915 hit it first.
Key follows the established convention — first six slug words plus
sha1(value)[:8], verified by reproducing 9.2.0's key from its title — and the
title is translated in all five locales alongside the English, matching how every
earlier release title is carried.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Docs only. Fills a gap #899 opened and I did not close.
The gap
PROTOCOL.mddocuments the envelope down topayload [11..]and stops — so the two bytes every reply actually opens with are described nowhere, even though #899 made both decoders publish them and addedCommandResultto the shared schema.Three places were describing the same layout ad hoc instead:
DeviceConfigReadProbeandFeatureFlagProbeeach say "the 2-byte response header (pay[1]is the 5/MG result code)" in their own comments, and the ECG paragraph mentions a result code in passing.New §2.4 states it once, for both families —
resp_cmd/resp_seq/resultat[6][7][8]on 4.0 and the same+4on 5/MG — plus thatresp_seqis the strap's own counter, not the echoed host-assigned envelopeseq(a real capture shows envelopeseq147 besideresp_seq2, and a repeatedresp_seqis what identified a duplicated write in #791).The part worth writing down
The first body byte.
GET_BATTERY_LEVELputs the charge percentage there —47in the hardware-confirmed fixture — so the slot carries real data. On every other captured command it has only ever been1:GET_BATTERY_LEVELGET_DATA_RANGESELECT_WRIST, acceptedSELECT_WRIST, refusedTOGGLE_LABRADOR_*For the wrist and ECG commands what that
1means is recorded as open. SendingSELECT_WRISTwith argument0got1back, which refutes an echo of the request — but every frame captured had a stored value of1, so "reads back stored state" and "this handler writes a literal1" predict identically on all of them. The decoder deliberately leaves the byte unnamed; this documents why, and what would settle it (a reply from a strap whose stored value is0— the #891 ask).Mechanics
Old §2.4 Checksums and §2.5 Reassembly shift to §2.5/§2.6. I checked: no cross-reference anywhere in the tree points at either, and the only internal PROTOCOL.md section reference is §2.2, unchanged.
Section is in §2 near the envelope, so it does not collide with #896, #898 or #907 — all three touch
PROTOCOL.mdbut in the ECG and device-config sections.Every claim was verified against source before writing: both platforms' offsets read out of the decoders, the PENDING-then-SUCCESS and
UNSUPPORTED(3)-on-haptics results traced to the captures that produced them, and the body-byte table recomputed from the committed fixtures rather than copied from the issue thread.