Site: the developer docs (phase 4), with the Debug Builds and the Debug Console first
CI / build (pull_request) Successful in 8m38s
Site / build (pull_request) Successful in 9s

/dev/ has Debug Builds and the Debug Console (builds and the token, the
console and its protocol, files and screenshots, driving the UI, crashes and
Safe Mode, the command reference), Build, test and release (including how an
update works), the architecture decisions and the milestone plans.

Generated from the repository by site/tools/gen_dev_docs.py: the ADRs, the
milestones, the README's sections, and the command reference, read from the
firmware's own `help` text. The pages are committed (Zola cannot read outside
its folder); the Site workflow checks they are current, and now also runs
when src/main.cpp changes. M0, M1 and CONTEXT.md are not published.
README: the gnss commands that the table lacked.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-06 21:25:33 +02:00
co-authored by Claude Sonnet 5.5
parent 8f95bee744
commit 3b4100dc6a
43 changed files with 2284 additions and 6 deletions
@@ -0,0 +1,55 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 316" role="img" aria-label="The life of an update. One: install, the image goes to app1 and the OTA data marks it NEW. Two: restart, the bootloader turns NEW into PENDING_VERIFY and boots app1. Three: Probation, 30 seconds up, a frame drawn, and Wi-Fi within 3 minutes if it is configured. Four: confirmed, the firmware marks itself VALID and a Toast says Updated. If it crashes or restarts before step four, the bootloader turns PENDING_VERIFY into ABORTED and boots app0 again, which says the update failed. Meanwhile app0 kept the previous firmware: the way back. The trap, under step two: Arduino's initArduino marks the image VALID before setup runs, unless verifyRollbackLater returns true.">
<defs>
<marker id="pb-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="currentColor"/></marker>
<marker id="pb-arrow-ok" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path class="f-green" d="M0,0 L10,5 L0,10 z"/></marker>
<marker id="pb-arrow-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path class="f-red" d="M0,0 L10,5 L0,10 z"/></marker>
</defs>
<g font-family="JetBrains Mono, ui-monospace, monospace" fill="currentColor">
<rect class="pb-box" x="16" y="40" width="170" height="80" rx="6"/>
<text x="28" y="62" font-size="12" font-weight="600">1 install</text>
<text x="28" y="84" font-size="11">image → app1</text>
<text x="28" y="102" font-size="11" class="pb-dim">otadata: NEW</text>
<rect class="pb-box" x="206" y="40" width="170" height="80" rx="6"/>
<text x="218" y="62" font-size="12" font-weight="600">2 restart</text>
<text x="218" y="84" font-size="11">bootloader:</text>
<text x="218" y="102" font-size="11" class="pb-dim">NEW → PENDING_VERIFY</text>
<rect class="pb-hot" x="396" y="40" width="170" height="80" rx="6"/>
<text x="408" y="62" font-size="12" font-weight="600">3 Probation</text>
<text x="408" y="84" font-size="11">30 s up, a frame</text>
<text x="408" y="102" font-size="11" class="pb-dim">Wi-Fi within 3 min</text>
<rect class="pb-ok" x="586" y="40" width="158" height="80" rx="6"/>
<text x="598" y="62" font-size="12" font-weight="600">4 confirmed</text>
<text x="598" y="84" font-size="11">→ VALID</text>
<text x="598" y="102" font-size="11" class="pb-dim">Toast: Updated to…</text>
<path class="pb-line" d="M186 80 H202" marker-end="url(#pb-arrow)"/>
<path class="pb-line" d="M376 80 H392" marker-end="url(#pb-arrow)"/>
<path class="pb-line-ok" d="M566 80 H582" marker-end="url(#pb-arrow-ok)"/>
<rect class="pb-bad" x="396" y="196" width="348" height="76" rx="6"/>
<text x="408" y="218" font-size="12" font-weight="600">crash or restart before 4</text>
<text x="408" y="240" font-size="11">bootloader: PENDING_VERIFY → ABORTED</text>
<text x="408" y="258" font-size="11" class="pb-dim">boots app0: "Update to … failed"</text>
<path class="pb-line-bad" d="M481 120 V192" marker-end="url(#pb-arrow-bad)"/>
<text x="408" y="294" font-size="10" class="pb-dim">(second line: bootGuard() in setup() rolls back</text>
<text x="408" y="308" font-size="10" class="pb-dim"> a second unconfirmed start by itself)</text>
<text x="16" y="216" font-size="11" class="pb-dim">app0 keeps the</text>
<text x="16" y="232" font-size="11" class="pb-dim">previous firmware:</text>
<text x="16" y="248" font-size="11" class="pb-dim">the way back</text>
<rect class="pb-trap" x="206" y="176" width="170" height="122" rx="6"/>
<text class="f-red" x="218" y="198" font-size="12" font-weight="600">the trap</text>
<text x="218" y="220" font-size="11">initArduino()</text>
<text x="218" y="238" font-size="11">marks it VALID</text>
<text x="218" y="256" font-size="11">before setup(),</text>
<text x="218" y="274" font-size="11" class="pb-dim">unless verify-</text>
<text x="218" y="290" font-size="11" class="pb-dim">RollbackLater()</text>
<path class="pb-line-bad" d="M291 176 V124" marker-end="url(#pb-arrow-bad)"/>
<text x="16" y="22" font-size="13" font-weight="600">The life of an update</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB