phase: 01_verification_gate
All green. Report: **Implemented / verified (phase 01 final pass)** - `.agents/validate.sh` re-verified as the gate: ①`tests/run_tests.sh` ②`SANITIZE=1` run ③`uv … platformio run -e bridge -e console` ④page byte count ⑤hygiene, then the informational `tools/hw_probe.sh`. Added an explicit `== repo hygiene ==` header + `repo hygiene: OK (57 tracked files…)` verdict line so every check prints one (previously hygiene passed in silence). - `.agents/HW_VERIFICATION.md`: baseline (bridge 26.7 %/87 592 B, 36.1 %/1 135 293 B; console 16.8 %/33.6 %; 3406 checks; page 48 598 B) re-confirmed; served-page row extended with this pass's one-attempt measurements. **Tests / gate (100 % green)** - `bash .agents/validate.sh` → **exit 0** (also from `/tmp`): `RESULT: all suites passed` twice (3406 = 3162 C++ + 160 relayctl + 84 page), `2 succeeded`, `page bytes: 48598`, `repo hygiene: OK`, `validation OK`. - Faults re-demonstrated then reverted: (a) inverted `test_keystate` assert → cold-copy gate `RESULT: FAILED`, **GATE_EXIT=1**; (b) markup id `pArmed`→`pArmedZ` → page suite rc 1; (c) type error in `src/main.cpp` → `bridge FAILED / console FAILED`, rc 1; (d) hygiene regex matches `certs/test.pem` (git index commands are forbidden in this pass — task 01's report holds the original live `git add` demo). - Lint: no linter is configured for this repo; compiler is the linter — `-Wall -Wextra` host suites + both firmware builds: **0 warnings**; `bash -n` clean; `py_compile` clean. `ruff check` (this machine's broad ruleset) reports 21 pre-existing *preview-rule* style nits in untouched `tools/*.py` + `tests/test_relayctl.py` (SIM/UP/ISC/EXE/RUF/FURB), zero correctness findings — not churned: `watch_target.py`/`relayctl.py` are hardware-verified artifacts outside this phase. `shellcheck` is absent here and not in the local container image (fetching it would violate the gate's no-network rule). Coverage: n/a (shell + docs; no new Python). **Completion criteria** — all met: exit 0 with per-check output ✓; SANITIZE in-gate ✓; no `-t upload`/device curl/network fetch (grep: only in comments; `run_tests.sh` checks `podman image exists` first, so never pulls) ✓; faults bite ✓; HW_VERIFICATION.md names command+expected observation for every 02–05 device claim + one-attempt rule ✓; full suite green, `git status` = phase artifacts + mandated doc edits, nothing stray ✓. **Documentation** — README inconsistencies found & fixed: `test_proto` 193→**2327** (table now sums to the headline 3406); duplicate stale `test_page 47` row deleted (element-id clause merged into the 84 row); "last six checks"/"fails 3 checks" claims replaced by measurement (5 fail-safe source pins; `linked()` gate → 2, accept-stamp → 1, both → 3); console line formats corrected to what the code prints (`mouse interface=present target=report protocol buttons=0x00 …`, `queue 0 keys pending…`, `target=BOOT protocol (refused)`); status-JSON sample gained `typed/typing/mouse/mbtn/mframes`; footprint 87 400/35.5 %→87 592/36.1 %; page delivery `Content-Length: 35164`→**48 598** (re-measured live, one capped curl: 200/48 598, 404 on `/nope`, 401 on `/status`); stale Backlog item "Mouse." removed and renumbered; "~35 KB"→"~48 KB"; page-button names matched to the real markup; `validate.sh`/`HW_VERIFICATION.md`/`hw_probe.sh` added to Architecture, Tests and End-to-end. AGENTS.md: only stale statements fixed — "one commit, `Initial import`… predates the mouse and `output.h`" and the pure-module list missing `mouse.h`/`output.h`; not expanded. **Deviations** — Did not run the keystroke/mouse device rows: the board's target is this very machine, so injecting input during an unattended pass is the side effect the README's "hazard nobody warns you about" forbids; those rows stay blank per the contract (read-only GETs only). No live infra changed. **Next pending phase:** `02_tls_control_channel` (tasks `01_tls_identity_module` … `06_tls_docs_rollback`).
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
# HW_VERIFICATION.md — the device half of this roadmap's verification
|
||||
|
||||
The host gate (`.agents/validate.sh`) proves what can be proven without a board:
|
||||
the pure-module suites under sanitisers, the page and tool suites, both firmware
|
||||
builds, repo hygiene. It deliberately contains **no** `-t upload`, no `curl` to a
|
||||
device, no network fetch — an upload in a gate is a device side effect on
|
||||
somebody else's schedule (AGENTS.md).
|
||||
|
||||
That leaves claims that only a device can answer. AGENTS.md's standard:
|
||||
*"A feature that lives on the device is not done when the source builds — it is
|
||||
done when the device is running it and something observed it."* This file pairs
|
||||
every such claim in phases 02–05 with the exact command that observes it and the
|
||||
observation that counts, and states the rule that keeps a unit from ever blocking
|
||||
on a board nobody is holding.
|
||||
|
||||
`bash tools/hw_probe.sh` (printed at the end of every gate run, exit status
|
||||
deliberately ignored) says what is reachable *right now* — serial nodes,
|
||||
`keyrelay.local`, http/https, `uv`/`node`, target-side evdev nodes — without
|
||||
side effects and without blocking. It informs; it never gates and never records
|
||||
an outcome by itself.
|
||||
|
||||
## Baseline (measured, phase 01 task 01 gate run)
|
||||
|
||||
Later phases quote a **delta against these numbers**, never a fresh guess.
|
||||
|
||||
| metric | value |
|
||||
|---|---|
|
||||
| `bridge` RAM | 26.7 % (87 592 / 327 680 B) |
|
||||
| `bridge` Flash | 36.1 % (1 135 293 / 3 145 728 B) |
|
||||
| `console` RAM | 16.8 % (55 200 / 327 680 B) |
|
||||
| `console` Flash | 33.6 % (1 056 081 / 3 145 728 B) |
|
||||
| host checks | **3406** (3162 C++ + 160 `relayctl` + 84 page), green in the normal **and** the `SANITIZE=1` run |
|
||||
| served page | **48 598 bytes** — the raw-string length the gate prints every run; a reflashed device must serve exactly this many |
|
||||
|
||||
Phase 02 additionally quotes the heap cost of one and two live TLS sessions as a
|
||||
delta against the `bridge` RAM/heap line above.
|
||||
|
||||
## Claims that need hardware
|
||||
|
||||
Outcome vocabulary, written into the row **in the phase's commit** by whoever ran
|
||||
the command: `ok` · `skipped (no device)` · `failed: <what>`. Blank = not run
|
||||
yet. A row nobody ran is recorded `skipped (no device)` at phase close — an
|
||||
unobserved claim is never back-filled with a guess (ASSUMPTION: unattended runs
|
||||
may have a board attached that nobody is watching, and a second machine for
|
||||
`watch_target.py` is rarer than either).
|
||||
|
||||
### Every phase that touches the keystroke path (02–05 regression baseline)
|
||||
|
||||
| claim | command | expected observation | outcome |
|
||||
|---|---|---|---|
|
||||
| keystrokes reach the target | `python3 tools/watch_target.py --seconds 60` **on the target**, driven from the page or `tools/relayctl.py` | one press **and** release per key with timestamps; `still held` absent from the summary | |
|
||||
| a chord is the keys its label claims | `python3 tools/relayctl.py --host keyrelay.local chord 04 2b` while `watch_target.py` runs | `LAlt press` then `Tab press` — and **not** `LCtrl`. The watcher is the only thing that says what the target received (README: Alt+Tab was `Ctrl+Alt+A` on the wire once) | |
|
||||
| served page == built page | `curl -s http://keyrelay.local/ \| wc -c` (after phase 02 lands: `curl -sk https://keyrelay.local/ \| wc -c`) | byte-equal to the `page bytes:` line the gate prints. A mismatch means the page in flash is stale — reflash **and** reload any open tab | ok — measured 2026-11-09: `curl -s http://keyrelay.local/ \| wc -c` = 48598 = gate's count (board on the LAN, pre-TLS, serving over http as expected). Re-run by the phase 01 final pass, one capped attempt each: 200 / 48 598 bytes, 404 on `/nope`, 401 on `/status` without the token, zero `src=`/`href=` in the served bytes. The first cold probe returned nothing (`http_code=000`, glibc does not cache mDNS) and the retry worked — that retry is the documented behaviour, not a second attempt at the check |
|
||||
| silence disarms | arm, kill the controller process without a clean close (or close the tab), wait `kNoClientTimeoutMs` (8 s), `python3 tools/relayctl.py --host keyrelay.local status` | `armed: 0`, and `watch_target.py` shows releases for anything held. Test the *timer*, not the socket close (README bug 10) | |
|
||||
| nothing outlives the link | hold a key and a mouse button, then drop the link | every key up, every button up; mouse summary shows no `still held` | |
|
||||
|
||||
### Phase 02 — HTTPS + `wss://`
|
||||
|
||||
| claim | command | expected observation | outcome |
|
||||
|---|---|---|---|
|
||||
| TLS handshake completes | `curl -sk https://keyrelay.local/status` or `openssl s_client -connect keyrelay.local:443 </dev/null` | 200 + status JSON / a session whose only verify failure is *self-signed*. `HTTP 000` / connection refused = listener not up | |
|
||||
| fingerprint printed **once**, on serial | serial console boot log after `nvs erase`; then `python3 tools/console.py cert` (opens the port — one attempt, capped) | SHA-256 fingerprint appears exactly once at first boot, on demand afterwards; **never** the key; survives reflashing (NVS) | |
|
||||
| pinned fingerprint == handshake cert | `openssl s_client -connect keyrelay.local:443 </dev/null 2>/dev/null \| openssl x509 -noout -fingerprint -sha256` | same hex as the serial console printed; mismatch = two identities, investigate before pinning | |
|
||||
| `:80` is redirect-only | `curl -s -o /dev/null -w '%{http_code} %{redirect_url}' http://keyrelay.local/` | 3xx to `https://`, and **no page bytes** on plaintext | |
|
||||
| plaintext `/ws` refused, not downgraded | a `ws://` upgrade attempt on `:80` (e.g. `curl -i -N` with upgrade headers, or `relayctl.py` pointed at plaintext) | refused loudly (per README error style), never a silent plaintext session | |
|
||||
| TLS session heap cost | build RAM delta from the gate output + live free-heap readout the phase's `status`/serial path exposes, at 0 / 1 / 2 live sessions | quoted as a delta against the baseline table above; two sessions must fit without allocation failure | |
|
||||
| `-D KR_TLS=0` rollback behaves like today | build the rollback env, flash once, `curl -s http://keyrelay.local/ \| wc -c` + page connects over `ws://` | page and `ws://` work exactly as pre-phase-02; README documents the rollback | |
|
||||
|
||||
### Phase 03 — session takeover
|
||||
|
||||
| claim | command | expected observation | outcome |
|
||||
|---|---|---|---|
|
||||
| takeover releases the incumbent's held keys | two controllers on one board: incumbent holds a key, newcomer takes over (`relayctl.py --take-over`), all while `watch_target.py` runs **on the target** | `watch_target.py` shows the key **up** *before* the new session's first key-down — the ordering is the whole claim | |
|
||||
| the board comes back disarmed | `python3 tools/relayctl.py --host keyrelay.local status` immediately after the handover | `armed: 0` across the handover; the newcomer must arm again on purpose; nothing in the handover path arms | |
|
||||
| a third controller is still refused | a third `/ws` upgrade while two sessions exist | `E3` — takeover consumes the one spare slot, it does not open the door | |
|
||||
|
||||
### Phase 04 — responsive page
|
||||
|
||||
| claim | command | expected observation | outcome |
|
||||
|---|---|---|---|
|
||||
| page still byte-exact after the restructure | the generic `curl … \| wc -c` row above | equals the gate's new `page bytes:` count (the count moves when the page does — that is fine; equality with the gate is the check) | |
|
||||
| one column on a phone, ARM thumb-reachable | open `https://keyrelay.local/` on a phone at ~360 px | single column, no horizontal scroll, sticky ARM bar on screen, log collapsed and not pushing ARM off screen | |
|
||||
|
||||
### Phase 05 — soft keyboard and touch pad
|
||||
|
||||
| claim | command | expected observation | outcome |
|
||||
|---|---|---|---|
|
||||
| arm on a phone raises the soft keyboard, characters land | phone on the board's AP/network, tap ARM, type a word; `watch_target.py` **on the target** | phone keyboard appears; the watcher's `typed:` line reproduces exactly what was typed, one `P=0:` character per frame | |
|
||||
| a latched modifier chords correctly | latch Ctrl on the row, tap `c`; watch on the target | `LCtrl press` + `C press` — Ctrl+C on the wire, latch visibly cleared after | |
|
||||
| pad moves the pointer; lift releases everything | press-and-hold the pad, move, lift; hold a button meanwhile, then drop the link | `movement dx … dy …` lines that **stop at lift**; `still held` absent from the mouse summary; no button stuck | |
|
||||
|
||||
## The blocking rule
|
||||
|
||||
A unit running any of the rows above:
|
||||
|
||||
1. **Look first, side-effect-free.** `bash tools/hw_probe.sh` (always exits 0,
|
||||
every probe capped, no serial port opened — opening `/dev/ttyACM*` toggles
|
||||
DTR/RTS and resets the board). It tells you whether an attempt is plausible.
|
||||
2. **One attempt, capped.** Each device step runs **at most once**, wrapped in
|
||||
`timeout` (or the tool's own `-m`). No polling a port, no retry loops, no
|
||||
re-powering, no re-flashing "to see if it works". A timeout is an outcome
|
||||
(`failed: timeout …` or `skipped (no device)`), not a cue to try again.
|
||||
3. **Record what was observed.** The outcome — `ok`, `skipped (no device)`,
|
||||
`failed: …` — plus the exact command written goes into the row above, in the
|
||||
phase's commit. Never write `ok` for a command that did not run; the
|
||||
unattended-run contract is that the human picks these rows up later.
|
||||
4. **Never strand the board.** `tools/to_bootloader.py` drops the board into ROM
|
||||
download mode *deliberately*, and a power cycle is the only way back. If a
|
||||
run leaves the board in download mode, its report says so explicitly —
|
||||
nobody may be there to notice.
|
||||
5. **Never block the gate.** None of this is inside `.agents/validate.sh`. The
|
||||
gate stays device-free and network-free; the probe line at its end is context
|
||||
whose exit status is deliberately discarded.
|
||||
@@ -0,0 +1,18 @@
|
||||
All green. Report:
|
||||
|
||||
**Implemented / verified (phase 01 final pass)**
|
||||
- `.agents/validate.sh` re-verified as the gate: ①`tests/run_tests.sh` ②`SANITIZE=1` run ③`uv … platformio run -e bridge -e console` ④page byte count ⑤hygiene, then the informational `tools/hw_probe.sh`. Added an explicit `== repo hygiene ==` header + `repo hygiene: OK (57 tracked files…)` verdict line so every check prints one (previously hygiene passed in silence).
|
||||
- `.agents/HW_VERIFICATION.md`: baseline (bridge 26.7 %/87 592 B, 36.1 %/1 135 293 B; console 16.8 %/33.6 %; 3406 checks; page 48 598 B) re-confirmed; served-page row extended with this pass's one-attempt measurements.
|
||||
|
||||
**Tests / gate (100 % green)**
|
||||
- `bash .agents/validate.sh` → **exit 0** (also from `/tmp`): `RESULT: all suites passed` twice (3406 = 3162 C++ + 160 relayctl + 84 page), `2 succeeded`, `page bytes: 48598`, `repo hygiene: OK`, `validation OK`.
|
||||
- Faults re-demonstrated then reverted: (a) inverted `test_keystate` assert → cold-copy gate `RESULT: FAILED`, **GATE_EXIT=1**; (b) markup id `pArmed`→`pArmedZ` → page suite rc 1; (c) type error in `src/main.cpp` → `bridge FAILED / console FAILED`, rc 1; (d) hygiene regex matches `certs/test.pem` (git index commands are forbidden in this pass — task 01's report holds the original live `git add` demo).
|
||||
- Lint: no linter is configured for this repo; compiler is the linter — `-Wall -Wextra` host suites + both firmware builds: **0 warnings**; `bash -n` clean; `py_compile` clean. `ruff check` (this machine's broad ruleset) reports 21 pre-existing *preview-rule* style nits in untouched `tools/*.py` + `tests/test_relayctl.py` (SIM/UP/ISC/EXE/RUF/FURB), zero correctness findings — not churned: `watch_target.py`/`relayctl.py` are hardware-verified artifacts outside this phase. `shellcheck` is absent here and not in the local container image (fetching it would violate the gate's no-network rule). Coverage: n/a (shell + docs; no new Python).
|
||||
|
||||
**Completion criteria** — all met: exit 0 with per-check output ✓; SANITIZE in-gate ✓; no `-t upload`/device curl/network fetch (grep: only in comments; `run_tests.sh` checks `podman image exists` first, so never pulls) ✓; faults bite ✓; HW_VERIFICATION.md names command+expected observation for every 02–05 device claim + one-attempt rule ✓; full suite green, `git status` = phase artifacts + mandated doc edits, nothing stray ✓.
|
||||
|
||||
**Documentation** — README inconsistencies found & fixed: `test_proto` 193→**2327** (table now sums to the headline 3406); duplicate stale `test_page 47` row deleted (element-id clause merged into the 84 row); "last six checks"/"fails 3 checks" claims replaced by measurement (5 fail-safe source pins; `linked()` gate → 2, accept-stamp → 1, both → 3); console line formats corrected to what the code prints (`mouse interface=present target=report protocol buttons=0x00 …`, `queue 0 keys pending…`, `target=BOOT protocol (refused)`); status-JSON sample gained `typed/typing/mouse/mbtn/mframes`; footprint 87 400/35.5 %→87 592/36.1 %; page delivery `Content-Length: 35164`→**48 598** (re-measured live, one capped curl: 200/48 598, 404 on `/nope`, 401 on `/status`); stale Backlog item "Mouse." removed and renumbered; "~35 KB"→"~48 KB"; page-button names matched to the real markup; `validate.sh`/`HW_VERIFICATION.md`/`hw_probe.sh` added to Architecture, Tests and End-to-end. AGENTS.md: only stale statements fixed — "one commit, `Initial import`… predates the mouse and `output.h`" and the pure-module list missing `mouse.h`/`output.h`; not expanded.
|
||||
|
||||
**Deviations** — Did not run the keystroke/mouse device rows: the board's target is this very machine, so injecting input during an unattended pass is the side effect the README's "hazard nobody warns you about" forbids; those rows stay blank per the contract (read-only GETs only). No live infra changed.
|
||||
|
||||
**Next pending phase:** `02_tls_control_channel` (tasks `01_tls_identity_module` … `06_tls_docs_rollback`).
|
||||
@@ -0,0 +1 @@
|
||||
ok
|
||||
@@ -0,0 +1,151 @@
|
||||
== host suites: bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== host suites: SANITIZE=1 bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
sanitizers: on
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== firmware: platformio run -e bridge -e console ==
|
||||
Processing bridge (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/bridge/partitions.bin
|
||||
Retrieving maximum program size .pio/build/bridge/firmware.elf
|
||||
Checking size .pio/build/bridge/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [=== ] 26.7% (used 87592 bytes from 327680 bytes)
|
||||
Flash: [==== ] 36.1% (used 1135293 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.84 seconds =========================
|
||||
|
||||
Processing console (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/console/partitions.bin
|
||||
Retrieving maximum program size .pio/build/console/firmware.elf
|
||||
Checking size .pio/build/console/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [== ] 16.8% (used 55200 bytes from 327680 bytes)
|
||||
Flash: [=== ] 33.6% (used 1056081 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.83 seconds =========================
|
||||
|
||||
Environment Status Duration
|
||||
------------- -------- ------------
|
||||
bridge SUCCESS 00:00:00.844
|
||||
console SUCCESS 00:00:00.833
|
||||
========================= 2 succeeded in 00:00:01.676 =========================
|
||||
|
||||
== page size: src/web_page.h raw string ==
|
||||
page bytes: 48598 (a reflashed device must serve exactly this many; kIndexHtmlLen is sizeof(kIndexHtml)-1 of this same string)
|
||||
|
||||
== repo hygiene ==
|
||||
repo hygiene: OK (57 tracked files, no ignored-tracked files, no key-material shapes, no PII hits)
|
||||
|
||||
== hardware context (informational; cannot change the gate result) ==
|
||||
hw-probe serial /dev/ttyACM0 present, readable (NOT opened: opening toggles DTR/RTS and resets the board)
|
||||
hw-probe mdns keyrelay.local resolves -> 10.2.0.22
|
||||
hw-probe https https://keyrelay.local/ unreachable (curl rc 7, code 000) — expected until phase 02 (TLS) lands
|
||||
hw-probe http http://keyrelay.local/ -> HTTP 200, no redirect (plaintext page still served: the pre-phase-02 shape)
|
||||
hw-probe uv /home/ducoterra/.local/bin/uv — firmware builds available
|
||||
hw-probe node /usr/bin/node — test_page.js runs
|
||||
hw-probe evdev board 046d:c33f visible: keyboard=/dev/input/event19 (readable) mouse=/dev/input/event20 (readable) — python3 tools/watch_target.py runs ON THIS machine (the target)
|
||||
validation OK (suites + sanitised suites + bridge/console builds + page size + hygiene)
|
||||
@@ -0,0 +1,14 @@
|
||||
Everything green. Final report:
|
||||
|
||||
**Implemented**
|
||||
- Rewrote `.agents/validate.sh` (adapted the generic template) as keyrelay's real gate, `rc`-accumulating, any-cwd, no `set -e` swallowing: ① `bash tests/run_tests.sh` ② `SANITIZE=1` run ③ `uv run --python 3.14 --with platformio python -m platformio run -e bridge -e console` (missing `uv` = FAIL with the AGENTS.md fallback-probe message; never `-t upload`) ④ page byte count from the `R"HTML(` raw string ⑤ the template's three hygiene gates verbatim. Added a python3/node presence check so the suite can't silently skip.
|
||||
- `.gitignore` already had `.agents/phase-sessions/` + `.agents/pipeline.log` — no edit needed.
|
||||
|
||||
**Tests** (`bash .agents/validate.sh`, also from `/tmp`): **exit 0**, ~9 s — `RESULT: all suites passed` (3406 checks: 3162 C++ + 160 relayctl + 84 page) in normal **and** sanitised runs; `bridge SUCCESS RAM 26.7% (87 592 B) / Flash 36.1% (1 135 293 B)`, `console SUCCESS RAM 16.8% (55 200 B) / Flash 33.6% (1 056 081 B)`; `page bytes: 48598`; `validation OK`.
|
||||
**Fault injection, each → gate exit 1, then reverted + green re-confirmed**: (a) inverted `CHECK(!s.dirty())` → exit 1; (b) markup id `pArmed`→`pArmedZ` → page suite FAIL, exit 1; (c) `int kr_injected_fault_c[2] = "…"` in `main.cpp` → bridge+console FAILED, exit 1; (d) tracked `certs/test.pem` → hygiene FAIL exit 1, `git rm --cached` done, index verified clean, `git diff` empty. Gate contains no upload/curl/pull/network command (grep-verified; only a quoted warning in `echo`).
|
||||
|
||||
**Docs**: README "Controller page" said "~35 KB" — stale (measured 48 598 B); now states the exact gate-counted figure. AGENTS.md: no stale facts created; not expanded (its policy).
|
||||
|
||||
**Decisions**: missing `uv`/deps fail rather than skip (per task ASSUMPTION); the page-size check fails if the raw-string markers aren't exactly one each; output is full (RAM/Flash captured for task 02's baseline table).
|
||||
|
||||
**Next task**: `01_verification_gate/02_hardware_contract.md` (`.agents/HW_VERIFICATION.md` + `tools/hw_probe.sh`).
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
== host suites: bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== host suites: SANITIZE=1 bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
sanitizers: on
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== firmware: platformio run -e bridge -e console ==
|
||||
Processing bridge (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/bridge/partitions.bin
|
||||
Retrieving maximum program size .pio/build/bridge/firmware.elf
|
||||
Checking size .pio/build/bridge/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [=== ] 26.7% (used 87592 bytes from 327680 bytes)
|
||||
Flash: [==== ] 36.1% (used 1135293 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.84 seconds =========================
|
||||
|
||||
Processing console (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/console/partitions.bin
|
||||
Retrieving maximum program size .pio/build/console/firmware.elf
|
||||
Checking size .pio/build/console/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [== ] 16.8% (used 55200 bytes from 327680 bytes)
|
||||
Flash: [=== ] 33.6% (used 1056081 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.86 seconds =========================
|
||||
|
||||
Environment Status Duration
|
||||
------------- -------- ------------
|
||||
bridge SUCCESS 00:00:00.844
|
||||
console SUCCESS 00:00:00.856
|
||||
========================= 2 succeeded in 00:00:01.700 =========================
|
||||
|
||||
== page size: src/web_page.h raw string ==
|
||||
page bytes: 48598 (a reflashed device must serve exactly this many; kIndexHtmlLen is sizeof(kIndexHtml)-1 of this same string)
|
||||
validation OK (suites + sanitised suites + bridge/console builds + page size + hygiene)
|
||||
@@ -0,0 +1,10 @@
|
||||
**Report — task `01_verification_gate/02_hardware_contract.md`**
|
||||
|
||||
- **Implemented**
|
||||
- `.agents/HW_VERIFICATION.md`: Baseline table (bridge RAM 26.7 %/87 592 B, Flash 36.1 %/1 135 293 B; console 16.8 %/55 200 B, 33.6 %/1 056 081 B; 3406 checks; page 48 598 B); per-phase claim tables for the keystroke-path regression baseline and phases 02–05 (chord identity via `watch_target.py`, `curl … | wc -c` vs gate count http→https, TLS handshake + one-time serial fingerprint + `:80` redirect-only + ws refusal + heap delta, takeover key-up-before-first-key + `armed:0` + `E3`, phone layout, soft keyboard/latch/touch-pad), each row with command + expected observation + outcome slot; the blocking rule (one `timeout`-capped attempt, record `ok`/`skipped (no device)`/`failed:`, no port polling, no opportunistic reflash, explicit note if left in ROM download mode, gate stays device-free).
|
||||
- `tools/hw_probe.sh` (executable, `set -uo pipefail`): 7 fact lines — serial nodes (stat-only, never opened), mDNS, https, http+redirect, `uv`, `node`, board evdev nodes (same USB-id + `capabilities/ev` classification as `watch_target.py`); every probe capped; always exits 0.
|
||||
- `.agents/validate.sh`: appended `bash tools/hw_probe.sh || true` as the last, explicitly non-`rc` line with the why.
|
||||
- **Tests** (all green): `bash .agents/validate.sh` → exit 0 — `RESULT: all suites passed` (3406) normal + `SANITIZE=1`; bridge+console SUCCESS with baseline RAM/Flash; page bytes 48598; hygiene OK; probe context printed without affecting rc. Probe: exit 0 from repo root and `/tmp`, with uv stripped, and in a minimal PATH (no `timeout`/`getent`/`dirname` → states reasons, never hangs; 1.8 s full run); wrapper survives a probe that dies non-zero. `shellcheck` (cached podman image): rc 0, zero findings. Live one-attempt check recorded honestly: `curl -s http://keyrelay.local/ | wc -c` = 48598 = gate count (`ok` row).
|
||||
- **Docs**: no README change — “End-to-end verification” matches every probed fact (http 200 no-redirect, mDNS resolves, no TLS yet); the historical 1.0.0 `Content-Length: 35164` row belongs to phase 04 task 03’s byte-check re-derivation. No AGENTS.md change (no statement went stale; not expanded per its policy).
|
||||
- **Decisions**: probe never opens serial or blocks (degrades to stated “unknown” when its caps are missing); one real device row filled to demonstrate the outcome format; no firmware source touched.
|
||||
- **Next task**: `02_tls_control_channel/01_tls_identity_module.md`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
== host suites: bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== host suites: SANITIZE=1 bash tests/run_tests.sh ==
|
||||
compiler: g++ inside localhost/ai-sandbox:ubuntu-9a08b1d500b0 (repo mounted at /work)
|
||||
sanitizers: on
|
||||
keystate 40 checks, 0 failures
|
||||
proto 2327 checks, 0 failures
|
||||
text 459 checks, 0 failures
|
||||
mouse 48 checks, 0 failures
|
||||
output 153 checks, 0 failures
|
||||
ws_codec 135 checks, 0 failures
|
||||
handshake
|
||||
frame encoding
|
||||
frame decoding
|
||||
key table
|
||||
pasted text
|
||||
mouse
|
||||
protocol strings
|
||||
the fail-safe wiring
|
||||
the target-side verifier
|
||||
t= 0.00s >>> Ctrl+Alt+Del <<<
|
||||
relayctl 160 checks, 0 failures
|
||||
the log stays readable
|
||||
characters
|
||||
key names in the log
|
||||
sending text
|
||||
refusing what it cannot type
|
||||
stopping
|
||||
the mouse
|
||||
element ids
|
||||
page 84 checks, 0 failures
|
||||
RESULT: all suites passed
|
||||
|
||||
== firmware: platformio run -e bridge -e console ==
|
||||
Processing bridge (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/bridge/partitions.bin
|
||||
Retrieving maximum program size .pio/build/bridge/firmware.elf
|
||||
Checking size .pio/build/bridge/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [=== ] 26.7% (used 87592 bytes from 327680 bytes)
|
||||
Flash: [==== ] 36.1% (used 1135293 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.84 seconds =========================
|
||||
|
||||
Processing console (platform: espressif32@8.0.0; board: esp32-s3-devkitc-1; framework: arduino)
|
||||
--------------------------------------------------------------------------------
|
||||
Verbose mode can be enabled via `-v, --verbose` option
|
||||
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1.html
|
||||
PLATFORM: Espressif 32 (8.0.0) > Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)
|
||||
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
|
||||
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
|
||||
PACKAGES:
|
||||
- framework-arduinoespressif32 @ 4.30312.261024 (3.3.12)
|
||||
- framework-arduinoespressif32-esp32s3-libs @ 3.3.12
|
||||
- tool-esptool @ 2.50400.0 (5.4.0)
|
||||
- tool-riscv32-esp-elf-gdb @ 12.1.0+20221002
|
||||
- tool-xtensa-esp-elf-gdb @ 12.1.0+20221002
|
||||
- toolchain-riscv32-esp @ 14.2.0+20260121
|
||||
- toolchain-xtensa-esp-elf @ 14.2.0+20260121
|
||||
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
|
||||
LDF Modes: Finder ~ chain, Compatibility ~ soft
|
||||
Found 45 compatible libraries
|
||||
Scanning dependencies...
|
||||
Dependency Graph
|
||||
|-- Adafruit NeoPixel @ 1.15.5
|
||||
|-- ESPmDNS @ 3.3.12
|
||||
|-- USB @ 3.3.12
|
||||
|-- Preferences @ 3.3.12
|
||||
|-- WiFi @ 3.3.12
|
||||
Building in release mode
|
||||
Generating partitions .pio/build/console/partitions.bin
|
||||
Retrieving maximum program size .pio/build/console/firmware.elf
|
||||
Checking size .pio/build/console/firmware.elf
|
||||
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
|
||||
RAM: [== ] 16.8% (used 55200 bytes from 327680 bytes)
|
||||
Flash: [=== ] 33.6% (used 1056081 bytes from 3145728 bytes)
|
||||
========================= [SUCCESS] Took 0.83 seconds =========================
|
||||
|
||||
Environment Status Duration
|
||||
------------- -------- ------------
|
||||
bridge SUCCESS 00:00:00.837
|
||||
console SUCCESS 00:00:00.834
|
||||
========================= 2 succeeded in 00:00:01.671 =========================
|
||||
|
||||
== page size: src/web_page.h raw string ==
|
||||
page bytes: 48598 (a reflashed device must serve exactly this many; kIndexHtmlLen is sizeof(kIndexHtml)-1 of this same string)
|
||||
|
||||
== hardware context (informational; cannot change the gate result) ==
|
||||
hw-probe serial /dev/ttyACM0 present, readable (NOT opened: opening toggles DTR/RTS and resets the board)
|
||||
hw-probe mdns keyrelay.local resolves -> 10.2.0.22
|
||||
hw-probe https https://keyrelay.local/ unreachable (curl rc 7, code 000) — expected until phase 02 (TLS) lands
|
||||
hw-probe http http://keyrelay.local/ -> HTTP 200, no redirect (plaintext page still served: the pre-phase-02 shape)
|
||||
hw-probe uv /home/ducoterra/.local/bin/uv — firmware builds available
|
||||
hw-probe node /usr/bin/node — test_page.js runs
|
||||
hw-probe evdev board 046d:c33f visible: keyboard=/dev/input/event19 (readable) mouse=/dev/input/event20 (readable) — python3 tools/watch_target.py runs ON THIS machine (the target)
|
||||
validation OK (suites + sanitised suites + bridge/console builds + page size + hygiene)
|
||||
Reference in New Issue
Block a user