Skip to content

fix(firmware): take the device back out of WiFi update mode when a flash fails (part of #269) - #445

Merged
tylerkron merged 2 commits into
mainfrom
fix/269-restore-lan-mode-on-failed-wifi-update
Aug 6, 2026
Merged

fix(firmware): take the device back out of WiFi update mode when a flash fails (part of #269)#445
tylerkron merged 2 commits into
mainfrom
fix/269-restore-lan-mode-on-failed-wifi-update

Conversation

@tylerkron

@tylerkron tylerkron commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Part of #269 (item 2 — removes the consumer-side recovery workaround).

Not merging — this is for your review.

The bug

UpdateWifiModuleAsync sends SYSTem:COMMUnicate:LAN:FWUpdate, which bridges USB straight through to the WINC and bypasses the device's SCPI console. Only the successful path walked it back out. A failed flash, a state timeout, or a cancel left the module unreachable until someone power-cycled the device.

That is precisely why daqifi-desktop still wraps Core's call in its own recovery finally (SerialStreamingDevice.ResetLanAfterUpdate + a raw transparent-mode exit) — one of the workarounds #269 exists to move into Core.

The fix

Both failure exits of WifiModuleUpdater.RunUpdateAsync now run a best-effort bridge exit before reporting the failure. It is the managed-connection twin of the already-shipped WifiBridgeActivator.Deactivate — same two commands, same order, same pause:

SYSTem:USB:SetTransparentMode 0   →   100 ms   →   SYSTem:COMMunicate:LAN:APPLY

The pause is now one shared internal constant rather than two copies, so the raw-serial path and the managed path cannot pace the same firmware transition differently.

Design calls worth reviewing:

  • Not the success path's full LAN:ENAbled/APPLY/SAVE restore. Persisting a network configuration off the back of a flash that did not complete is not this step's job; the job is only to make the device answerable again. This also keeps the failure path from adding WiFi connect churn beyond the single APPLY that leaves bridge mode.
  • Never throws. The caller still sees the original failure, unchanged — a recovery that cannot reach the device must not replace the reason the update failed.
  • Runs on a token of its own, never the caller's. On the cancellation path the caller's token is canceled by definition, and that is exactly when the device most needs the exit.
  • Bounded by the post-flash reconnect budget (ReconnectingAfterFlashVerifyingTimeout). Same physical operation — waiting for the serial transport to come back — and already tunable by a host that knows its re-enumeration is slow.
  • Armed before prep, not after the update-mode command inside it. A cancel or state timeout can land between the command reaching the device and the method regaining control, so Core cannot know how far prep got. A redundant bridge exit on a device that never entered update mode is a no-op (bench-confirmed below); a skipped one strands a bridged module.

No new options. No public API change. WifiBridgeActivator.InterCommandDelay went from private to internal.

Tests

+3 (2690 → 2693). Full suite green on net9.0 and net10.0: 2693 passed / 2 skipped each, +23 Mcp on net9, 0 warnings.

  1. Flash tool fails → exact recovery sequence sent, device reconnected first (prep had disconnected it), original FirmwareUpdateException/Programming unchanged.
  2. Canceled after LAN:FWUpdate but before prep's disconnect → recovery still runs on its own token; DisconnectCalls == 0 pins that the exit is not conditional on having been disconnected.
  3. Recovery budget spent by the time the bridge-exit pause elapses → the sequence still finishes, and the original cancellation still surfaces unchanged. (Rewritten by the review fix below — it originally pinned the opposite, torn-in-half outcome.)
  4. Recovery budget expires while waiting for a transport that never comes back → nothing is sent and the original flash failure surfaces. (Added by the review fix.)
  5. Device was never connected → no recovery attempted at all, ConnectAttempts == 0, immediate failure. (Added by the review fix.)

The existing happy-path test already asserts the success sequence by exact equality, so "no bridge exit on success" stays pinned there.

Mutation-checked, 6/6 caught: recovery never runs (3 fail), skip recovery when the caller canceled (2), drop the inter-command pace (1), swap the two commands (3), send the full ENAbled/APPLY/SAVE instead (2), and an unbounded recovery budget — which hangs the suite rather than failing a test, since the reconnect loop then has nothing to stop it. Source restored from a byte-identical backup (sha verified) before committing.

Note for anyone repeating this: deleting the recovery calls outright does not compile under TreatWarningsAsErrors (CS0219, the flag becomes write-only), so that mutation had to be expressed as an always-true guard inside the helper.

Bench (real Nq1, fw 3.7.2, USB, non-destructive)

Scratchpad harness ProjectReference'd at this branch's Core.

  • Negative control first — bogus SYSTem:NOTAREALCOMMAND?-113,"Undefined header". Without it the clean queues below would be worthless evidence.
  • SYSTem:USB:SetTransparentMode 0 with the 102 ms pace → scpiErrors=none. This is the already-off no-op path, i.e. exactly what the conservative arming hits on a device that never entered bridge mode.
  • Repeat of the same exit (a consumer with its own finally, or a retried update) → scpiErrors=none.
  • WINC chip info identical before and after: id=1377184 fw=19.7.7 build=Mar 30 2022. Device still answering, final queue clean.

Deliberately not exercised, and the harness gates on it rather than assuming: the trailing LAN:APPLY was skipped because the probe found the WINC powered, where APPLY starts a real WiFi association and connect-churn is a known way to wedge this bench unit. LAN:APPLY is unchanged shipped behavior on both the success path and WifiBridgeActivator.Deactivate; the ordering and pacing around it are pinned by the unit tests above. SetTransparentMode 1 was never sent — it is unrecoverable over a managed connection, which is also why "wrong order fails" cannot be shown non-destructively.

Merge safety

Verified with git merge-tree against both open loop PRs: clean against #443 and clean against #444. Hunks were mapped first and deliberately placed clear of both.


Review fix (1967c2e)

Both Qodo findings addressed — full reasoning in this comment.

"Recovery armed too early" — valid, fixed as suggested. mayBeInLanUpdateMode was armed before the prepare step, so a device that was never connected — and therefore never bridged — still ran the recovery, whose reconnect loop then waited out the full ReconnectingAfterFlash budget (45 s by default). An immediate "device must be connected" failure became a 45-second one. Armed inside the prepare delegate now, immediately after the LAN:FWUpdate send — as early as it can honestly be, since Send is synchronous and no await separates it from the assignment.

"Missing pre-send cancel check" — the race is real, the prescribed fix inverts the helper's purpose. Guarding the sends with the budget token could only ever turn a recovery that had already got the transport back into a device left bridged. The genuine problem the finding surfaced is that the budget was observed by the pause between the two commands but not by the sends around it, so the sequence could be torn in half — console handed back, WiFi manager still in its bridge-mode state machine. The budget now bounds the reconnect wait and nothing else, and the two-command exit runs to completion once the transport is back; the un-cancelled tail is a fixed 100 ms plus two synchronous writes.

Tests: +2 net (2693 → 2695), zero losses. FULL suite green net9 + net10 (2695 passed / 2 skipped each, +23 Mcp on net9), 0 warnings. Mutation-checked 4/4 on the fix itself. git merge-tree re-verified clean against #443 and #444.

Bench re-run (real Nq1, fw 3.7.2, USB, non-destructive) — 5/5. Negative control (-113,"Undefined header") first, then the paced SetTransparentMode 0 exit and a repeat of it both scpiErrors=none (elapsed 102 ms), WINC chip info identical before/after, final queue clean.

…ash fails (part of #269)

`UpdateWifiModuleAsync` puts the device into LAN firmware-update mode, which
bridges USB straight through to the WINC and bypasses the SCPI console. Only
the *successful* path walked it back out, so a failed or canceled flash left
the module unreachable until someone power-cycled the device.

That is the gap `daqifi-desktop` compensates for with its own recovery
`finally` (`ResetLanAfterUpdate` + a raw transparent-mode exit) around Core's
call — one of the workarounds #269 exists to move into Core.

Both failure exits now run a best-effort bridge exit before reporting the
failure. It is the managed-connection twin of the already-shipped
`WifiBridgeActivator.Deactivate`: `SYSTem:USB:SetTransparentMode 0`, the same
100 ms pause, then `LAN:APPLY` to kick the WiFi manager out of its bridge-mode
state machine. The pause is now a single shared constant so the two paths that
walk a device out of bridge mode cannot pace it differently.

Deliberately not the success path's full `LAN:ENAbled`/`APPLY`/`SAVE` restore:
persisting a network configuration off the back of a flash that did not
complete is not this step's job. It never throws, so the caller still sees the
original failure, and it runs on a token of its own — on the cancellation path
the caller's token is canceled by definition, and that is exactly when the
device most needs the exit. Bounded by the post-flash reconnect budget, which
is the same physical operation and already tunable.

No new options and no public API change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tylerkron
tylerkron requested a review from a team as a code owner August 6, 2026 04:25
@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Restore device LAN mode after failed/canceled WiFi module update

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Send a best-effort bridge-exit sequence when WiFi flashing fails or is canceled.
• Share a single inter-command delay constant across raw-serial and managed recovery paths.
• Add regression tests covering flash-tool failure, cancellation timing, and recovery budget expiry.
Diagram

graph TD
  svc["FirmwareUpdateService"] --> updater["WifiModuleUpdater"] --> state{"Failure / cancel?"} --> recovery["Bridge-exit recovery"] --> dev(["Streaming device"])
  updater --> flash[["WINC flash tool"]]
  recovery --> delay["WifiBridgeActivator delay"]

  subgraph Legend
    direction LR
    _svc["Service/module"] ~~~ _ext[["External process"]] ~~~ _dev(["Device/transport"])
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extract a shared 'bridge-exit' helper used by both paths
  • ➕ Eliminates duplication between managed recovery and WifiBridgeActivator.Deactivate
  • ➕ Ensures command ordering/delay stay identical as behavior evolves
  • ➖ Requires designing a shared abstraction that works for both raw-serial and managed device APIs
  • ➖ Slightly larger refactor than needed for a targeted bug fix
2. Always run recovery in a single outer finally around the full update
  • ➕ Simplifies reasoning: one guaranteed exit attempt regardless of where failure occurred
  • ➕ Reduces reliance on a 'may be in update mode' flag
  • ➖ Harder to preserve correct failed-state reporting unless carefully ordered
  • ➖ May attempt reconnect/exit even before update-mode entry unless additional state is tracked
3. Perform full LAN restore (LAN:ENAbled/APPLY/SAVE) on failure
  • ➕ Could return device to a known network configuration automatically
  • ➖ Risks persisting configuration after an incomplete/failed flash
  • ➖ Adds extra device churn and side effects beyond making the device reachable again

Recommendation: The PR’s approach is the best tradeoff for #269 item 2: it is best-effort, bounded, non-throwing, and focuses solely on restoring reachability (transparent-mode off + LAN:APPLY) without persisting network configuration after a failed flash. Consider a follow-up refactor to centralize the shared bridge-exit sequence (not just the delay) if both the raw-serial and managed paths will continue to evolve.

Files changed (3) +261 / -1

Bug fix (2) +94 / -1
WifiBridgeActivator.csExpose shared inter-command delay for bridge exit sequence +8/-1

Expose shared inter-command delay for bridge exit sequence

• Promotes the transparent-mode inter-command pause to an internal constant with documentation. This allows the managed recovery path to match the raw-serial deactivation pacing exactly.

src/Daqifi.Core/Firmware/WifiBridgeActivator.cs

WifiModuleUpdater.csBest-effort exit from LAN FWUpdate mode on failure/cancel +86/-0

Best-effort exit from LAN FWUpdate mode on failure/cancel

• Tracks whether the device may have entered LAN firmware-update (bridge) mode, and on both exception and cancellation paths attempts a bounded recovery sequence. Recovery waits for reconnect if needed, sends SetTransparentMode(0), delays using the shared constant, then sends LAN:APPLY; it never throws and preserves the original failure state/exception.

src/Daqifi.Core/Firmware/WifiModuleUpdater.cs

Tests (1) +167 / -0
FirmwareUpdateServiceTests.csAdd regression tests for bridge-exit on failed/canceled WiFi updates +167/-0

Add regression tests for bridge-exit on failed/canceled WiFi updates

• Adds three tests asserting that a failed flash, a cancellation after entering update mode, and a recovery-budget expiry all still attempt the bridge-exit sequence. Verifies command ordering, reconnect behavior, and that the original failure/cancellation remains the surfaced outcome.

src/Daqifi.Core.Tests/Firmware/FirmwareUpdateServiceTests.cs

@qodo-code-review

qodo-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Missing pre-send cancel check ✗ Dismissed 🐞 Bug ☼ Reliability
Description
TryLeaveLanUpdateModeAfterFailureAsync uses a timeout token (restoreCts.Token) but does not
check it immediately before each synchronous device.Send(...), so the recovery budget can expire
and the method can still start sending a state-changing command. This creates a race where
LAN:APPLY (or the transparency-mode exit) may be sent after the configured recovery timeout should
have stopped further device mutations.
Code

src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[R938-941]

+            await Task.Delay(WifiBridgeActivator.InterCommandDelay, restoreCts.Token).ConfigureAwait(false);
+
+            device.Send(ScpiMessageProducer.ApplyNetworkLan);
+
Relevance

●●● Strong

Strong precedent: add cancellation guard immediately before state-changing SCPI writes to avoid
post-cancel mutation.

PR-#315
PR-#324

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The recovery token is observed by Task.Delay, but the follow-on device.Send(ApplyNetworkLan) has
no cancellation/timeout guard, so it can still start after token cancellation. In contrast, the
existing raw-serial bridge-exit path checks cancellation immediately before writing each SCPI
command, demonstrating the intended pattern for avoiding post-cancel state changes.

src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[926-941]
src/Daqifi.Core/Firmware/WifiBridgeActivator.cs[279-287]
PR-#315

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The recovery sequence is intended to be bounded by `restoreCts`’s timeout, but it only passes the token into `Task.Delay(...)`. There is no `ThrowIfCancellationRequested()` immediately before `device.Send(...)`, so a timeout/cancel can occur after the delay completes (or right after reconnect) and the subsequent `Send` can still execute.

### Issue Context
`device.Send(...)` is synchronous and cannot be interrupted once started, so the critical behavior is to avoid starting any new send after the recovery token has been canceled.

### Fix
Add `restoreCts.Token.ThrowIfCancellationRequested();` immediately before:
- `device.Send(SetUsbTransparencyMode(0))`
- `device.Send(ApplyNetworkLan)`
(and optionally immediately after the reconnect completes and after the delay completes) to ensure no command begins after the recovery budget expires.

### Fix Focus Areas
- src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[926-941]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Recovery armed too early ✓ Resolved 🐞 Bug ☼ Reliability
Description
WifiModuleUpdater.RunUpdateAsync sets mayBeInLanUpdateMode = true before it verifies the device
is connected, so early failures (e.g. EnsureDeviceConnected throwing) still run the bridge-exit
recovery and can block for up to VerifyingTimeout attempting reconnect and sending recovery SCPI
commands. This turns a fast “device must be connected” failure into a potentially long reconnect
loop and can run redundant state-changing commands on devices that never entered FW-update mode.
Code

src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[R79-82]

+            // the device and this method regaining control, so Core cannot know how far prep got.
+            // A redundant bridge-exit on a device that never entered update mode is a no-op; a
+            // skipped one leaves a bridged device needing a power cycle. Bias to the harmless side.
+            mayBeInLanUpdateMode = true;
Relevance

●● Moderate

Team likes precondition/side-effect boundaries, but PR intent explicitly arms early to avoid
stranding bridged devices.

PR-#391
PR-#153

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The flag is set before the prepare step runs, but the prepare step itself first enforces
connectivity and can throw when disconnected; that exception is caught by the outer catch which now
always runs the recovery when the flag is true. The recovery calls WaitForSerialReconnectAsync,
which loops device.Connect() attempts until its token cancels, introducing the extra wait on what
used to be an immediate disconnected-device failure.

src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[74-109]
src/Daqifi.Core/Firmware/FirmwareUpdateContext.cs[283-315]
src/Daqifi.Core/Firmware/FirmwareUpdateContext.cs[317-323]
src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[910-941]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`mayBeInLanUpdateMode` is set to `true` before the prepare-state delegate runs. If the prepare delegate fails immediately (e.g. `EnsureDeviceConnected` throws because the device is disconnected), the failure handler still calls `TryLeaveLanUpdateModeAfterFailureAsync`, which can wait for serial reconnect for the full reconnect budget and may send bridge-exit commands unnecessarily.

### Issue Context
The intent is to avoid stranding devices when cancellation/timeouts happen around `LAN:FWUpdate`, but arming the flag outside the prepare delegate broadens recovery to cases where the update-mode command could not have been sent.

### Fix
Move the arming of `mayBeInLanUpdateMode` into the prepare-state action immediately before issuing the update-mode command (or set it only after a successful write attempt), while still keeping it early enough to cover cancellation/timeouts inside preparation.

### Fix Focus Areas
- src/Daqifi.Core/Firmware/WifiModuleUpdater.cs[74-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/Daqifi.Core/Firmware/WifiModuleUpdater.cs Outdated
Comment thread src/Daqifi.Core/Firmware/WifiModuleUpdater.cs Outdated
…lf done

Two review findings on the failure-path bridge exit.

Arming `mayBeInLanUpdateMode` before the whole prepare step meant an
`EnsureDeviceConnected` failure — a device that was never connected, so
never bridged — still ran the recovery, whose reconnect loop then waited
out the full ReconnectingAfterFlash budget (45s by default) for a
transport that was never gone. An immediate "device must be connected"
failure became a 45-second one.

It is now armed inside the prepare step, immediately after the
`LAN:FWUpdate` send. That is as early as it can honestly be: `Send` is
synchronous and no await separates it from the assignment, so nothing can
interleave between them, and everything above the send fails with the
command definitively un-sent. The original reason for arming early — a
cancel or state timeout landing while the device is still acting on a
command it already received — is unaffected, because that window opens
after the send, not before it.

Second, the recovery budget was observed by the pause between the two
exit commands, so it could send `SetTransparentMode 0` and then not send
`LAN:APPLY`. That half state is the one outcome worse than not starting:
the console is handed back while the WiFi manager is left in its
bridge-mode state machine, so the device answers SCPI while its module
still is not reachable. The budget now bounds only the reconnect wait —
the one step here that can take unbounded time — and the two-command exit
runs to completion once the transport is back. The un-cancelled tail is a
fixed pause plus two synchronous writes, so the helper stays bounded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tylerkron

Copy link
Copy Markdown
Contributor Author

Both Qodo findings addressed in 1967c2e — one accepted as described, one addressed in the opposite direction from the suggested fix, with reasoning below.

2. "Recovery armed too early" — valid, fixed as suggested

Real regression, and worse than the summary states. EnsureDeviceConnected is the first statement in the prepare delegate, so a device that was never connected — and therefore never bridged — was still arming the recovery. The recovery then called WaitForSerialReconnectAsync, which loops device.Connect() until its budget cancels. GetStateTimeout(ReconnectingAfterFlash) maps to VerifyingTimeout, 45 s by default, so an immediate "device must be connected" failure became a 45-second one.

Armed inside the prepare delegate now, immediately after device.Send(SetLanFirmwareUpdateMode). That is as early as it can honestly be: Send is synchronous and no await separates it from the assignment, so nothing can interleave between them. The original justification for arming early — a cancel or state timeout landing while the device is still acting on a command it already received — is untouched, because that window opens after the send, not before it. Everything above the send (EnsureDeviceConnected, StopStreaming) fails with the command definitively un-sent.

1. "Missing pre-send cancel check" — the race is real, the prescribed fix inverts the helper's purpose

The suggestion is to add restoreCts.Token.ThrowIfCancellationRequested() before Send(SetTransparencyMode 0) and before Send(ApplyNetworkLan). Taken literally that makes the bug worse, because of whose token this is.

WifiBridgeActivator.Deactivate — cited as precedent, and it does guard every write — observes the caller's token. The caller asked to stop, so Core must stop. TryLeaveLanUpdateModeAfterFailureAsync observes an internal budget token that this PR created; it is not user intent, and on the cancellation path the caller's token is canceled by definition. A guard before the first Send can only ever fire in the window between WaitForSerialReconnectAsync returning successfully and the send starting — i.e. it can only convert a recovery that had already got the transport back into a device left bridged. That is precisely the failure this PR exists to remove.

What the finding does correctly identify is an inconsistency: the budget was observed by the pause between the two commands but not by the sends around it, so the sequence could be torn in half. It could send SetTransparentMode 0 and then not send LAN:APPLY — console handed back, WiFi manager still in its bridge-mode state machine, so the device answers SCPI while the module is still unreachable. That half state is worse than either end.

Fixed by resolving the inconsistency the other way: the budget now bounds the reconnect wait and nothing else — the only step here that can take unbounded time — and the two-command exit runs to completion once the transport is back. The un-cancelled tail is a fixed 100 ms plus two synchronous writes, so the helper stays bounded. Note that Send is synchronous and uninterruptible once started anyway (as the finding itself observes), so the only decision available is whether to start it, and for a cleanup path the answer is yes.

The previous test that pinned the torn-in-half outcome was rewritten to pin the new intent, and a second test now covers the case the budget genuinely exists for.

Tests

+2 net (2693 → 2695), zero losses. FULL suite green net9 + net10 (2695 passed / 2 skipped each, +23 Mcp on net9), 0 warnings.

  • ..._WhenRecoveryBudgetExpiresAfterReconnect_StillFinishesTheBridgeExit — rewritten from the old mid-sequence test; budget (50 ms) is spent by the time the pace elapses and LAN:APPLY still goes out.
  • ..._WhenRecoveryBudgetExpiresWaitingForReconnect_SendsNoBridgeExit — new; device refuses every reconnect, recovery gives up after the budget, only LAN:FWUpdate on the wire, original flash failure still surfaces.
  • ..._WhenDeviceIsNotConnected_DoesNotAttemptTheBridgeExit — new; asserts ConnectAttempts == 0 and a sub-10 s elapsed against a deliberately generous 30 s VerifyingTimeout, so the regression above cannot come back silently.

Mutation-checked, 4/4 caught: arm before the prepare step again (1 fail — the disconnected-device test), put restoreCts.Token back on the pace (1 — the after-reconnect test), drop the bounded reconnect wait (2), arm after device.Disconnect() instead of after the send (2). Both sources restored from a byte-identical backup (sha verified) before committing.

git merge-tree --write-tree against #443 and #444: CLEAN — the arming moved to a line that neither PR touches.

Bench (real Nq1, fw 3.7.2, USB, non-destructive) — 5/5

Harness ProjectReference'd at this branch's Core. Negative control first, so the clean queues are real evidence: bogus SYSTem:NOTAREALCOMMAND?-113,"Undefined header". Then SetTransparentMode 0 + the 100 ms pace → scpiErrors=none (elapsed 102 ms); a repeat of it, which is exactly the redundant-exit path the arming comment calls harmless → scpiErrors=none; WINC chip info identical before and after (ChipId = 1377184, FwVersion = 19.7.7, BuildDate = Mar 30 2022); final queue clean.

Deliberately not sent: LAN:FWUpdate (bridge mode needs a power cycle to leave), SetUsbTransparentMode 1 (unrecoverable — the 0 that would undo it is forwarded to the WINC rather than interpreted), and LAN:APPLY on a powered WINC (connect-churn hazard). The ordering claims are pinned by the unit tests rather than the bench, and that limitation is stated rather than papered over.

Not merging — for review.

@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1967c2e

@tylerkron

Copy link
Copy Markdown
Contributor Author

Ready for review — not merging.

Verified on the exact head 1967c2e: CI build SUCCESS, MERGEABLE, origin/main (4b8eed2) confirmed an ancestor, and 0 unresolved review threads. Qodo's "Recovery armed too early" is struck through as ✓ Resolved; "Missing pre-send cancel check" was re-posted verbatim against the pre-fix code (it quotes a Task.Delay(..., restoreCts.Token) line the fix removed) and is answered and resolved in the thread above.

Full suite green net9 + net10 (2695 passed / 2 skipped each, +23 Mcp on net9), 0 warnings. Bench re-run on the real Nq1 (fw 3.7.2, USB, non-destructive) 5/5 with a negative control. git merge-tree clean against #443 and #444.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant