View this page on MeshCore Docs.
ESP32 native browser console startup - 2026-10-05
This is a local validation report, not a release approval. No GitHub upload, website deployment, or release publication is part of these results. The GUI time-sync connection timeout was reproduced on native USB. After the boot filesystem correction, the unchanged GUI's first fresh-flash connection passed on both the Heltec V4 and XIAO ESP32-S3. The final V4 600-second idle run also passed with power saving on, logging off, and no transmitted command during idle. Earlier terminal runs establish different boundaries and are recorded separately. The V4 core error flags changed during idle and are retained below; this is not a claim of error-free radio operation.
A later user screenshot identifies the affected surface as the Repeater / Room
server USB setup GUI at config.meshcore.io, with Cannot connect: Command
timeout: time <epoch>. The initial physical observations used the terminal at
flasher.meshcore.io/console. Native tests of the actual GUI were added after
identifying that mismatch and are recorded separately below.
Native test boundary
The physical target was a Heltec V4 ESP32-S3 Repeater attached to Mercerwood. Chromium 154.0.8037.92 ran on the Pi and used its actual OS Web Serial backend, native SerialPort objects, and native readable/writable streams. Playwright drove the full Vue website and recorded the UI and loader lifecycle. This is additional coverage beyond the physical Linux serial/Node Web Streams tests in the earlier OTA report.
The baseline firmware source was 7821329851f69b6b945f061bc4d15212d43c3198.
The unchanged website was pinned to upstream commit
45a5257bf792b11a83f4c51c18d4f312addfb677. Source hashes were checked before
flashing, including these production files:
| File | SHA-256 |
|---|---|
lib/console.js |
107d3ad867915aea8b2454c324327397a0f9e2f0469656046054011bc64475f9 |
js/flash.js |
e9762a29f6a91f8e33736e02ff41a81cd49e7b96fe253a5d71cba7daefd46d5b |
lib/esp32.js |
2a896d5e520ea9b6ea9900223c2460df797c3b2287f441daa4e50168a50b17e6 |
Only the unavailable headless permission chooser was replaced with selection
of the single, already granted V4. Before each application-only flash, native
ROM reads checked the 4096-byte partition table and OTA metadata. The table
hash was 9af3af2b74e944337ba85f2b0027ee80df160579a1ab746ba0f95853f618cd60;
valid OTA sequences 3 and 4 selected app1 at 0x650000. The UI's application
address was changed to that verified active slot. Full erase was disabled.
The actual stock loader write, native reset sequence, and disconnect remained
unchanged. No filesystem erase or additional backup was needed.
In the initial terminal experiments, the first command was sent after native open resolved with a 30-second deadline. The actual setup GUI kept its stock 5000 ms command deadline. No arbitrary startup sleep, extra reset, unplug/replug, keepalive, or automatic command retry was added to turn a failure into a pass. A first failure would remain a failure even if a separately recorded reopen recovered. USB-open readiness and firmware reply latency are separate measurements.
Completed physical observations
| Check | Observation |
|---|---|
| Baseline fresh application flash, same native port handle | PASS. The first ver reply took 9398 ms. Subsequent power-saving and core-stat queries passed. No unplug or additional reset was needed. Progress 100 preceded flashEsp32 completion by 604 ms. |
| Baseline power saving on, logging output off, 600 seconds idle | PASS with no transmitted command or keepalive during the idle interval. The post-idle ver reply took 5544 ms. Uptime advanced from 119 to 741 seconds, so the MCU did not reboot. Power saving remained on and logging remained off; temporary settings were restored afterward. |
| Stock website Close clicked immediately at the success heading, live site | PASS after reload; first ver took 1558 ms. The heading appeared 61.8 ms after progress 100, while both native streams were still locked. The original document continued through reset and disconnect; disconnect finished 987.3 ms after progress 100. |
| Same Close test with identical pinned HTML served locally at the official origin | PASS after reload; first ver took 1418 ms. The heading appeared 33.5 ms after progress 100 with both streams locked. Reset/disconnect still completed before navigation replaced the original document. The served index, app, and console hashes matched the unchanged pinned source. |
| Actual browser tab closed at the stock success heading, new tab in the same profile | PASS; first ver took 1575 ms. The tab-close request was emitted 126.5 ms after progress 100 with both streams locked. Reset and disconnect had not completed before that request. This used normal Page.close(run_before_unload=False), not the website Close/reload handler, browser shutdown, or a renderer kill. |
Local fixed terminal UI 452e6e7, final startup firmware 163364e52, actual tab close and 600 seconds idle |
PASS. Completion was exposed only after reset/disconnect, with native readable/writable streams already absent. First ver took 1408 ms; the post-idle reply took 1064 ms with power saving on and logging output off. Core-stat queries and preference restoration passed. This is terminal qualification, not GUI qualification. |
The stock completion display is demonstrably premature: progress 100 does not mean the loader has finished its tail, reset, and port release. However, both site Close tests and the actual tab-close test passed on this physical V4. The mock's canceled-tail ordering is not evidence that the physical device was left permanently hung. In particular, the tab-close request time is not the same as the time Chromium finished closing the target.
The qualified fresh-flash application SHA-256 was
912c1c5d80497de04a4ebd5d3a81b9275181ab2bb3bfb7f22e74c692ef0c5d8a.
The three completion/close experiments used the 2,093,336-byte application
ebee70b05528b21aaaeddf8bc80f2762b7ad767ff5b6f29eadf8e2a78e90859d.
Those terminal-only baseline passes did not establish a failing-baseline /
passing-fix comparison for the affected GUI. The later unchanged-GUI comparison
below provides that first-connect evidence.
Firmware startup correction and synthetic coverage
The startup changes are local firmware commits:
68a27a2eb: preserve initial HWCDC enumeration and the first console session on the pinned Arduino-ESP32 2.0.17 C3/S3 driver.a4e3a530c: capture startup reset classification in the pinned 3.3.11 ISR.163364e52: apply the same capture-only classification to the pinned 3.1.3 ISR used by the built XIAO C6 environment.c8c5f87ab: make ESP32 GPS discovery cooperative instead of blocking setup.0b9a80d7e: avoid repeated missing SPIFFS scans with a boot-only validated absence inventory; existing-file reads and mutations use the native backend.631f2ad97: check inventory lifetime and ordinary ESP32 build inclusion.
The startup predicate is captured when the native reset interrupt occurs, before delayed framework delivery can reclassify an initial enumeration as an active-session reset. Boot diagnostics and early RX do not end startup. The first application command-service loop ends startup; resets afterward retain the existing quarantine, queue purge, and session cleanup. Early command RX is retained until that loop can service it.
Delaying hardware USB data attachment through application setup is not a safe way to hide this startup boundary from the stock flasher. After progress 100, the unchanged loader still needs the native interface for RTS/reset and port cleanup. Withdrawing that interface during its tail can break the handoff. The selected correction keeps the transport available and retains first RX until command service is ready instead of forcing another physical reconnect.
Synthetic tests execute the pinned real driver ISR, production owner predicate, event handling, and session cleanup against host peripheral/RTOS stubs. They cover early and delayed enumeration, boot TX, boot RX, first-command retention, and a real reset after application readiness. Negative controls remove the startup gate, remove capture-time classification, arm on boot traffic, or leave startup suppression active forever. The removed protections cause the expected failures. Driver source pins, mode/version scope, unchanged SDK files, and idempotent build-local transforms are also checked.
The startup synthetic suites and V4/C6 builds passed. The earlier V4 full
Repeater build at 163364e52 passed its linked capability and memory checks.
Its application hash is
41ed8598aa2fb1b7aa5d320157249dc03a6e543051257c8b1d7d34d8e4c26df6.
The 3.x transforms only add startup reset classification; they do not import
the 2.0.17 TX/PHY backport or claim its guarantees. Unreviewed framework
versions keep their existing driver. C6 ISR tests and compilation do not
substitute for physical C6 qualification.
Five sequential qualified builds passed at source base 631f2ad97, with the
local test version v1.17.1.9-hil-bootfs-631f2ad9-631f2ad9. Their generated
capability/memory reports and application artifacts were retained privately.
This test version is not a published release.
| Requested build | Resolved environment and scope |
|---|---|
Full heltec_v4_repeater |
heltec_v4_repeater_observer_mqtt, PASS |
Full Xiao_S3_WIO_repeater |
Xiao_S3_WIO_repeater_observer_mqtt, PASS |
Full heltec_v4_room_server |
heltec_v4_room_server_observer_mqtt, PASS |
Ordinary Xiao_C6_repeater_ |
Complete supported profile with pinned Arduino-ESP32 3.1.3, PASS |
| Explicit Full XIAO S3 Companion | Xiao_S3_WIO_companion_radio_full, PASS |
The two physical unchanged-GUI first-connect passes below used the S3 Repeater images. The Room server and C6 results in this table qualify compilation and packaged capabilities, not physical GUI operation on those targets.
Local website correction and browser tests
Website commit 452e6e7 is local in a separate flasher checkout; the pinned
baseline source remains unchanged and the website has not been deployed.
Its three production changes are limited to index.html, js/app.js, and
lib/console.js:
- Show completion and expose Close only after the complete flash helper has finished reset/disconnect. Progress 100 alone shows restart in progress.
- Disable input until native open provides usable streams; report open, command, and disconnect failures explicitly.
- Recover a documented nonfatal RX error only when Web Serial supplies a fresh readable stream. Fatal errors disable input and require explicit reconnect.
- Release writers in
finallyand await actual read/write cleanup before closing. An uncancelable write reports a busy port rather than claiming success; the timeout is bounded per operation, not guaranteed cancellation.
All 16 full Vue/Chromium lifecycle tests passed, including five negative controls. They run the production UI, console, Web Streams, and flash/reset wrappers with mocked USB peripherals and loader data transfer. The immediate Close test uses a DOM MutationObserver so locator delay cannot miss the early completion race. Coverage includes delayed/failed open, nonfatal RX recovery, fatal RX, rejected writes, cancelable and uncancelable pending writes, slow reader cancellation, close errors, and flash-tail failure. The five controls restore progress-only completion, early editable input, missing RX recovery, missing writer cleanup, and the old fixed 50 ms close delay. Each fails for the intended missing protection. These tests establish client lifecycle behavior; they do not reproduce the user's physical hang.
Actual setup GUI handshake and regression comparison
The live setup GUI matches upstream meshcore-dev/config.meshcore.io commit
aff42ad8ef2b332f24d644ff6a783f8272a88ff2. The initial path is GUI Connect ->
native port open at 115200 -> held reader/writer -> time <epoch> -> getData.
There is no explicit DTR/RTS call on GUI open. The command is ASCII followed by
CR only. Its 5000 ms timer is armed before awaiting native writer.write, so both
write completion and response parsing must fit that deadline. The firmware
Repeater parser accepts CR and ignores LF; CR-only is a supported input path.
| GUI source | SHA-256 |
|---|---|
index.html |
efd64d1b56d57988fc4108f3f84efc943ed4c42ade4e4dbf8139c46fb3c0476d |
src/gui.js |
919034806e903fbc41e29a367a7d854837f6520f47aa34e5d0618f5dd3d29800 |
lib/serial-cli.js |
fbfbdcfa8bf1a372a0396d342e018ba8ee83d33b7b98c3a546fd37cd7e8ce870 |
The actual GUI page is preloaded before a separate tab runs the unchanged stock flash backend. After that backend returns, the GUI Connect button is clicked without reloading the GUI, inserting a settle delay, or changing its timeout. Each official origin is granted only the single intended native device. Raw GUI debug output and app.device are not retained: getData reads private keys and passwords. Lifecycle observations record command categories, byte counts, locks, timeouts, and safe numeric statistics without secret values.
Completed GUI configuration reads mean the unchanged getData flow returned and the GUI became connected. They do not exhaustively validate every field: the stock GUI can catch optional private-key, region, and ACL errors or skip an unsupported variable. The final XIAO run recorded no command-error events and completed its radio, region/default, and ACL commands as well as initial time.
| Actual GUI run | First attempt and separate recovery |
|---|---|
V4 163364e52, fresh flash |
FAIL. Initial time timed out at 5022 ms, and explicit stock cli.disconnect followed by GUI reconnect timed out at 5007.3 ms. Writes themselves completed in 4.7 and 29.3 ms. Only 147 boot RX bytes arrived; no command echo or reply marker was observed. Both locks remained held and GUI connected remained false. |
| Same V4 source, separate settled no-flash control | PASS. Initial time completed in 50.2 ms and the full GUI configuration read completed. This was a separate control, not a successful first fresh-flash attempt. |
V4 cooperative GPS source c8c5f87ab, fresh flash |
FAIL. Initial time timed out at 5024 ms. A separately recorded clean reopen completed time in 3336.2 ms and the full GUI read passed. Recovery does not change the first-attempt result. |
| Local XIAO ESP32-S3 Repeater, fresh flash | FAIL. Initial time timed out at 5001 ms. Separate clean reopen completed time in 3983.4 ms and the full GUI read passed. Native local Chromium and the target's own verified partition/active slot were used. |
| Same local XIAO, separate settled no-flash GUI control with 600 seconds idle | PASS. The initial GUI time completed in 9.9 ms and the full configuration read passed. With power saving on and logging off, no native writes occurred during the 600-second idle interval. Uptime advanced from 177 to 777 seconds, errors stayed at 0, and a visible GUI disconnect/reconnect reread passed. Original preferences were restored. This does not change the failed fresh-flash first attempt. |
V4 normal, untraced firmware 631f2ad97, fresh flash and 600 seconds idle |
PASS. Initial time completed in 420.7 ms and the full unchanged GUI read flow completed. With power saving on and logging off, zero native writes occurred during 600 seconds idle and uptime advanced from 18 to 618 seconds. Core err_flags changed from 0 to 8, setting the radio-watchdog bit. Visible GUI Disconnect/Connect completed a full reread, original preferences were restored, and final awaited Disconnect left port/reader/writer absent. |
XIAO normal, untraced firmware 631f2ad97, fresh flash |
PASS. Initial time completed in 3110.6 ms and the full unchanged GUI read passed. Core statistics reported uptime 4 seconds, errors 0, and queue length 1. No diagnostic reopen, extra reset, unplug/replug or timeout change was used. Final visible Disconnect completed with port, reader and writer absent. |
The native V4 failure is not just a pending write: both writes completed quickly.
The second attempt began about 10.48 seconds after the stock flash backend had
returned and still failed on 163364e52. A five-second GPS wait alone therefore
does not explain every observation. Cooperative GPS discovery removes that real
startup block, but its first GUI attempt still failed physically. That remaining
gap required the direct startup-phase diagnosis below.
The short GUI deadline and the terminal's 30-second test deadline are material
differences in coverage.
The final driver preserved the original command order and native calls. Source checks, permission selection, and ROM preflight occurred before application flashing; no settle sleep or additional USB operation was inserted after the stock flash backend returned. Automation and native-open latency are separate from the time command's elapsed response measurement: the final XIAO time began about 71 ms after backend return, while the V4 time began about 3586 ms later. Their 3110.6 ms and 420.7 ms reply times begin at command entry. Passing these cases does not claim that native port open or first command always occurs at zero elapsed time after a flash.
The final V4 application SHA-256 was
ffb0a00b97b382038db758954a38af464efe6b00bb88784936f9cc7c4b54db39.
Its final run recorded no client command-error events and no diagnostic reopen.
The final XIAO application SHA-256 was
b00ffbd0b7154f29741c3d93110705b33d3d34dcfa392ba7bd0e8e03d8cac9ce.
Its verified partition table hash was
f4e3b6cfe370c81dca210d57f3c463f924a539842a19fff6eda4615278ee97a2,
with parsed active app0 at 0x10000; the image fit that slot. Native Chromium
140.0.7339.186 ran locally on the VM. The V4 used the Pi's native Chromium.
In the stock GUI, a failed handshake alerts without disconnecting. The visible connected state stays false, while the native reader and writer remain owned. Retrying Connect can therefore encounter its own still-open port. The explicit cli.disconnect/reopen in these experiments is separately labeled diagnostic recovery, not an automatic retry added to the user's first handshake.
The hardware-free full Vue reproducer also shows the exact time alert when the mock initial write is delayed 9400 ms. The stock 5000 ms deadline fails while the native-style writer is pending; a separate runtime 15000 ms deadline control completes the same time command. That control is an ordering proof, not an unchanged-client fix or a reproduction of the native cause.
New CI coverage in test/test_official_config_gui.py executes the full SHA-pinned
stock SerialCLI and the exact GUI connect/disconnect functions in Node. Actual
production GPS init elapsed time controls command admission, and the production
Repeater command pump/CommonCLI time branch generate byte-fragmented replies.
The actual boot filesystem inventory and production recovery/presence paths
also supply a deterministic metadata-cost workload. Its absent native scans
cost 129 ms each plus 1000 ms setup settle: one inventory scan yields 1129 ms,
while the same workload without inventory performs 40 scans and yields 6160 ms.
These are modeled readiness costs, not predicted full physical boot times.
All six tests passed in local commit b259b1055. The four negative controls
restore blocking GPS, omit inventory, replace the CRLF reply with LF, or regress
CR command recognition. Each fails at the stock client-visible 5000 ms
initial-time boundary. getData is a callback witness there; full Vue fields,
enumeration, and other physical setup latency still require the native tests.
No complete third-party bundle is vendored.
The diagnostic V4 phase run retained its first time failure at 5026.1 ms and separate recovery at 2136.8 ms. Recovery core statistics reported uptime 16 seconds, errors 0, and queue length 1. The firmware's own millisecond phase timestamps locate setup work before the first CLI service:
| Measured startup phase | MCU interval and elapsed time |
|---|---|
| Sensors | 2815 -> 2829 ms, 14 ms |
| Dispatcher | 2829 -> 3714 ms, 885 ms |
| Preferences | 3714 -> 8261 ms, 4547 ms |
| Management state | 8261 -> 9941 ms, 1680 ms |
| ACL | 9941 -> 11104 ms, 1163 ms |
| Regions | 11104 -> 11362 ms, 258 ms |
| Filters | 11362 -> 12781 ms, 1419 ms |
| First CLI entry, ready admission, and available RX | All at 12796 ms |
No blocked CLI admission was reported before that first readiness; the first blocked-gate marker was later, at 14147 ms. The measured setup duration, rather than a new reset requirement or the GPS block alone, was the baseline first-time deadline problem. These trace intervals identify where to investigate; they do not by themselves prove a particular filesystem or CPU cause, or qualify an faster startup path. Qualification of that correction came from the subsequent unchanged-GUI first passes, rather than from trace intervals alone.
A qualified second run of the same granular trace application recorded the inner preference and management phases. It retained the initial time failure at 5024.1 ms and a separate recovery at 1787 ms; recovery core statistics were uptime 17 seconds, errors 0, and queue length 1. Its first CLI service was at 12805 ms. The earlier trace does not contain these inner markers.
| Qualified inner phase | MCU interval and elapsed time |
|---|---|
| Radio profile lookup | 3714 -> 4232 ms, 518 ms |
| OTA speed lookup | 4233 -> 4492 ms, 259 ms |
| Display settings lookup | 4492 -> 5010 ms, 518 ms |
| Common preference recovery | 5010 -> 6571 ms, 1561 ms |
| Existing common preference image, open through completed load | 6572 -> 6576 ms, 4 ms |
| MQTT preference recovery/read | 6577 -> 8266 ms, 1689 ms |
| Management route lookup | 8267 -> 9043 ms, 776 ms |
| Absent management reporter probes | 9043 -> 9561 ms, 518 ms |
These measurements separate slow missing-path metadata scans from the quick read of an existing preference image. No management reporter was allocated. The correction is a boot-only validated absence inventory, so known absent files can avoid repeated scans while existing-file reads, recovery, and mutation invalidation keep their native behavior. A failed or incomplete inventory falls back to native probes; existing-file errors remain delegated. Known absence is witnessed by the completed enumeration, so those cached negative lookups intentionally perform no later per-path metadata operation. The actual inventory negative controls and both normal-firmware unchanged-GUI first fresh-flash passes qualify the tested startup boundary.
Final target state
Final V4 readback reported uptime 718 seconds, active radio state 1(RX),
zero received packets, one sent packet, physical RX errors 0, err_flags 8,
and no outbound packet. This confirms active RX after the idle test without
identifying the exact past watchdog trigger. Power saving was restored off,
logging to USB, USB debug off, and MQTT and WebUI off/inactive. A manual
get bridge probe was unsupported and is retained as such, not counted as a
pass; the correct get bridge.enabled and get bridge.running readbacks
both returned off.
The local XIAO was restored to the latest tested Full Companion image at source
631f2ad97, application SHA-256
cf77ff2824f8359ab5e690424e5d6181911f401f0fe7b9a827550f13c0610e2c.
Native ROM preflight checked the target, partition table and OTA CRC selection
of app0. The filesystem and partition table were preserved.
Settled USB verification passed 60 requests with zero missed 2-second deadlines and maximum reply latency 7.152 ms. It covered ten held app/core pairs, ten reopen pairs, and ten seconds idle. The identity hash matched the recorded original, settings hashes remained stable, no input flush was used, and all serial handles closed. This restore check includes the helper's existing 250 ms open-handshake wait; it is not the fresh GUI's 5000 ms startup proof.
Qualification and limits
The affected first-connect timeout has a failing baseline and passing corrected normal-firmware result on both tested S3 boards. Diagnostic HIL_BOOT tracing was off in those passing images. The GUI timer and reset/reconnect behavior remained unchanged.
The final V4 fresh-flash 600-second idle test completed its uptime checks,
configuration reread, preference restoration, and awaited final disconnect.
The JSON field stats-core.errors is the err_flags bitmask serialized by
StatsFormatHelper.h, not an event counter. Its change from 0 to 8 sets
ERR_EVENT_RADIO_WATCHDOG (bit 3 in Dispatcher.h). It does not mean eight
errors. USB remained responsive, but this evidence alone does not identify
which radio-watchdog trigger path set the flag.
The XIAO Full Companion restoration is complete.
The local XIAO unchanged-GUI 600-second no-transmit idle control completed successfully with power saving on and logging off. Its successful initial settled handshake, uptime/error checks, full GUI reread, and preference restoration are separate from the failed first fresh-flash handshake. The already completed fixed-terminal 600-second run is also separate evidence.
These results do not qualify every host OS, USB adapter, cold power cycle, firmware role, high logging volume, or physical ESP32 board. A matching initial GUI timeout was reproduced and the tested first fresh-flash boundary now passes; idle results apply only to their measured configurations and intervals.
Evidence retention
The completed sanitized reports are retained privately under
/tmp/meshcore-hil-20261004/web-console-investigation. This document contains
no credentials, device identities, or raw console logs. Completed native reports
and their SHA-256 hashes are:
| Safe report | SHA-256 |
|---|---|
pi-chromium-baseline-fresh-flash-qualified-safe.json |
d01b18ce6a467f704605832d7a8adc1653999718f7cb4e23d11a9dd9d7bbc414 |
pi-chromium-baseline-power-idle-600-safe.json |
100d609d7a448ee223a86ec4ac6b2e14362f86d44ee2670b407815eff7c1b66d |
pi-chromium-stock-ui-immediate-close-safe.json |
32bcc0a67ea7716e2a0a0f60bf9081c4d2800bac3a8fe61f3595ee5d34b077c0 |
pi-chromium-stock-ui-fast-reload-close-qualified-safe.json |
b44e5d4885bb598596d021342692292c55c3f6f7a426c532845742caf8cb7e18 |
pi-chromium-stock-ui-tab-close-safe.json |
13557189ba0b68bb28837cc88b108d2df1536e583b96199027edeef307a7cadc |
pi-chromium-fixed-ui-final-firmware-idle-600-safe.json |
e1b3f14e5ae6d0762fc44ab4dc28b4b41a231415cae54b4cc5332f75bd46d926 |
pi-chromium-config-gui-baseline-fresh-flash-qualified-safe.json |
7abf519696c55d5af14d59c6781c644d7016d36f13d7c05833c23ce82b16f041 |
pi-chromium-config-gui-baseline-settled-control-safe.json |
da85499cebfddac700696cdfdf9ad6d96970932801af469552a2d91899c3a637 |
pi-chromium-config-gui-gps-fixed-fresh-flash-safe.json |
06c5525d66134cbbb460bf9e4e37e7ec74275559f1727f52cef889f074829e40 |
local-chromium-xiao-config-gui-fresh-flash-safe.json |
aa6c945f3d2c40b0db3e368a905ba38ab1a4d966f0d15b4d5848fccc88ff4f2b |
local-chromium-xiao-config-gui-settled-idle-600-safe.json |
3e7b996f13978574c77819ab80132d5c4452f8c7490ebb55333c124887f903bb |
pi-chromium-config-gui-startup-trace-fresh-flash-safe.json |
8062dfcdb202a2320c430e9f013f9510392f090a0883dc8fadbc296c92a46eed |
pi-chromium-config-gui-startup-granular-qualified-fresh-flash-safe.json |
10b269c68ef1e56a6104376d6c0b4f671bbe230ec005425a09cc7805953e07b0 |
local-chromium-xiao-config-gui-bootfs-fixed-fresh-flash-safe.json |
b94a53a4d017e95688c0231474c0aa0c67bc091b5738e0100173441d108db262 |
pi-chromium-config-gui-bootfs-fixed-fresh-flash-idle-600-safe.json |
8419f294aeeed087a43c1f062a109da2770f2dcfa79c52ac8aae72d82250cb05 |
bootfs-xiao-companion-restoration/flash-safe.json |
ae72ae2e3645735e44d46cb4d4a21920b7f669edb5571151e3a28ebafb89848c |
bootfs-xiao-companion-restoration/strict-USB-safe.json |
a8c56c8b7030ca5b5d18eed55f012e7227c9d234427e9e7df7e261b9cabb4dfa |
v4-bootfs-final-readback-safe.jsonl |
6186871dfed0f0a62bc35dc004c8eb971a5cd4ab3b81c0e11ab2aa9db00afc38 |
v4-bootfs-final-bridge-readback-safe.jsonl |
b26b9d104cd853208aff685f528659d2b1aa35cd2c802c1dd31c8288a04700ae |
The host reproductions are browser-console-lifecycle-mock-safe.json and
browser-flash-ui-early-completion-safe.json. Their mocked peripheral and
write-tail boundaries are recorded separately from native physical evidence.
The GUI timing control is
config-gui-investigation/gui-startup-timeout-mock-safe.json. Earlier GUI safe
reports used an overly strict observational time_reply_ok equality check for
plain OK; production returns OK - clock set: .... That metadata flag was
corrected to accept the prefix and never controlled first-connect PASS/FAIL.