chore(firmware): the bootloader's wire constants were written down twice - #519
Conversation
…loses #483) The SOH/EOT framing bytes, the DLE escape byte and the command opcodes were declared twice, verbatim — once in Pic32BootloaderMessageProducer and once in Pic32BootloaderMessageConsumer. Both copies were live: the producer writes them onto the wire and the consumer matches them coming back, so a one-sided edit would not fail loudly, it would mis-frame a live flash session on real hardware. They now live once, in an internal Pic32BootloaderWireFormat, with the values unchanged. Tests pin the byte values (the redundancy that used to come from having two copies now comes from the test file restating them), prove producer and consumer agree on every opcode without naming a value, and fail if either class re-declares a wire constant of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
PR Summary by QodoSingle-source PIC32 bootloader wire constants and add drift-guard tests
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR |
|
Qodo-clean, CI green — ready for review. (1 round on head |
What was wrong
The bytes that make up the PIC32 bootloader protocol — the start/end framing bytes, the escape byte, and the command opcodes — were written down twice, once in the class that sends messages to the bootloader and once in the class that reads its replies. Both copies were in use. Nothing checked that they still agreed, and nothing would have complained if they stopped: a one-sided edit would simply mis-frame a live firmware flash on real hardware, which is the worst place in this library to find out you have two sources of truth.
How it was fixed
The values now live in one internal
Pic32BootloaderWireFormatclass that both sides read from, unchanged byte for byte. The one thing worth pushing back on is that consolidating quietly removes a safety net: while there were two copies, a bad edit to one of them broke the other, and now a bad edit to the single copy just changes what Core puts on the wire. So the new tests restate the byte values explicitly — the second copy is now a test that has to be edited too, rather than a second copy in production code — and separately prove that the opcode the producer sends is the one the consumer expects back, without either value being named in the test.Verification
Pic32*test is unmodified and green; they hardcode the byte values independently, so they are the check that nothing moved.mainwas measured, not assumed. A throwaway harness dumped every message the producer builds (including 256 program-flash records chosen to exercise DLE escaping) and every decode outcome across the full 0–255 byte range, built against this branch and againstorigin/main: 1,285 lines, identical.closes #483
Not merging — for review.