diff --git a/assets/web/feature-workspaces.js b/assets/web/feature-workspaces.js index 0827917..a1b920f 100644 --- a/assets/web/feature-workspaces.js +++ b/assets/web/feature-workspaces.js @@ -199,15 +199,32 @@ function message(text,error=false){notice.textContent=translate(text);notice.classList.toggle('field-error',error);} const livePreview=input('checkbox');livePreview.checked=true; const livePreviewField=field('Live preview',livePreview);fixed.append(livePreviewField); + // Adapt Flutter's connectionRevision and foreground ownership. A board/boot + // alone is not the connection which acquired a temporary preview lease. + let pageLeaving=false; + function previewOwner(){ + if(!current(owner))return null; + try{const connection=pin?.();if(!connection)return null; + return {key:JSON.stringify([owner,connection]),editor:owner,pin:Object.freeze({...connection})}; + }catch{return null;} + } + function requirePreviewOwner(identity){requireCurrent(identity.editor);if(previewOwner()?.key!==identity.key)throw Error('Device connection changed. No preview was replayed.');} const preview=root.createPixelCorrectionPreview?.({ - owner:()=>current(owner)?{key:owner,pin:pin?.()}:null, - allowed:()=>current(owner)&&peer().has('pixel-corrections-preview')&&!!model?.saved&&!model.conflict&&validCorrectionDraft(model), + owner:previewOwner, + allowed:()=>!pageLeaving&&document.visibilityState!=='hidden'&¤t(owner)&&peer().has('pixel-corrections-preview')&&!!model?.saved&&!model.conflict&&validCorrectionDraft(model), configuration:()=>({revision:model.saved.revision,enabled:model.enabled,rules:model.rules}), pixels:()=>model.saved.pixels,project:correctionSources, - send:async(value,identity)=>{requireCurrent(identity.key);const reply=await command(correctionPath+'/preview',{configuration:JSON.stringify(value)});requireCurrent(identity.key);return reply.pixel_corrections_preview?{revision:value.revision,preview:reply.pixel_corrections_preview}:reply;}, - read:async identity=>{requireCurrent(identity.key);return api(correctionPath,identity.pin?{peer:identity.pin}:{});}, + // No named WS preview command exists. Use the shared fenced HTTP owner, + // retaining the acquisition pin through its asynchronous preflight too. + send:async(value,identity)=>{requirePreviewOwner(identity);const reply=await api(correctionPath+'/preview',{method:'POST',peer:identity.pin,body:new URLSearchParams({configuration:JSON.stringify(value)})});requirePreviewOwner(identity);return reply;}, + read:async identity=>{requirePreviewOwner(identity);const reply=await api(correctionPath,{peer:identity.pin});requirePreviewOwner(identity);return reply;}, onChange:state=>{if(state.error)message(state.error,true);} }); + const previewVisibility=()=>{if(document.visibilityState==='hidden')void preview?.stop();}; + const previewPageHide=()=>{pageLeaving=true;void preview?.stop();}; + const previewPageShow=()=>{pageLeaving=false;}; // BFCache return never starts output. + document.addEventListener?.('visibilitychange',previewVisibility); + root.addEventListener('pagehide',previewPageHide);root.addEventListener('pageshow',previewPageShow); livePreview.onchange=()=>{if(!livePreview.checked)void preview?.stop();else if(model?.dirty)startPreview();}; function startPreview(){if(!livePreview.checked||!preview||!validCorrectionDraft(model)||model.conflict)return;if(preview.snapshot().enabled)preview.edited();else void preview.start();} function changed(){if(!model)return;correctionEdits++;model.dirty=true;message(model.conflict?'Board changed elsewhere. Reload before saving.':'Unsaved changes',model.conflict);sync();if(model.mappingView==='draft')drawMapping();rememberPresentation();startPreview();} @@ -559,7 +576,7 @@ } const beforeUnload=event=>{if(groups?.dirty()||[...models.values()].some(record=>record.dirty||record.busy)){event.preventDefault();event.returnValue='';}}; root.addEventListener('beforeunload',beforeUnload); - installed={update,workspaceSnapshot(scope){return model&&model.scope===scope?diagnosticWorkspace(model.diagnosticDraft):undefined;},presentationSnapshot(scope){return model&&model.scope===scope?pixelToolsWorkspace(model.presentation):undefined;},dispose(){void preview?.dispose();disposed=true;dismissReload();root.removeEventListener('beforeunload',beforeUnload);groups?.dispose();userFiles?.dispose();corrections.card.remove();diagnostics.card.remove();inspector.card.remove();installed=null;}}; + installed={update,workspaceSnapshot(scope){return model&&model.scope===scope?diagnosticWorkspace(model.diagnosticDraft):undefined;},presentationSnapshot(scope){return model&&model.scope===scope?pixelToolsWorkspace(model.presentation):undefined;},dispose(){void preview?.dispose();disposed=true;dismissReload();document.removeEventListener?.('visibilitychange',previewVisibility);root.removeEventListener('pagehide',previewPageHide);root.removeEventListener('pageshow',previewPageShow);root.removeEventListener('beforeunload',beforeUnload);groups?.dispose();userFiles?.dispose();corrections.card.remove();diagnostics.card.remove();inspector.card.remove();installed=null;}}; update();return installed; } root.createFeatureWorkspaces=create; diff --git a/docs/FILE-COMPARISON.md b/docs/FILE-COMPARISON.md index 404bbd4..38d45c8 100644 --- a/docs/FILE-COMPARISON.md +++ b/docs/FILE-COMPARISON.md @@ -957,7 +957,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp/src/AvrIsp.h:66 [UTF8-LF sha256=03561fd6b5a97e9a178e3dd70888c8e068c7db58a357b26028353d959b5009ad; anchor=void report(]`. - Target: `mobile/lib/upgrade_observation.dart:3 [UTF8-LF sha256=8feabc680770f062a09ec3a5e7e72d1e9aad814335f630ddc00be3770790e8d7; anchor=class UpgradeObservation]`. - Target: `desktop/src/firmware_progress.rs:11 [UTF8-LF sha256=11188ec3c9bc7b89e76b94e5412f0e689fa656e5a636d4964136c2236aabbe31; anchor=pub struct Upgrade]`. -- Target: `firmware/esp/src/WebUi.h:2695 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function upgradeObservation(]`. +- Target: `firmware/esp/src/WebUi.h:2712 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function upgradeObservation(]`. - Retained: Complete canonical donor documentation read through EOF and original-byte SHA matched the inventory. Adapted the actual measured-stage/unknown-denominator/verified-completion/no-write-replay contract, not the donor's AVRDUDE parser: local HTTP raw file bytes, remote download stage bytes, coherent async-to-loop snapshots, finite AVR scheduled text leases and separate client reboot/readback verification. - Retained: Reread the complete canonical update-progress document for actual0.2.8 migration. Explicit exact-board maintenance admits only the older producer's update/backup observations, never ordinary controls; the new boot still passes the default release policy. Missing BOTH newer producer headers is confined to that selected recovery and retains same-address, whole MD5 and before/after board/boot checks. Failed manifest admission can preserve zero image metadata only with the exact pinned manifest/job/boot/target/zero bytes. Added backpressure-aware multipart chunks and explicit upload pacing; no automatic mutation retry. Real fixtures cover these boundaries. Actual HTTPS stage22/new boot/full running SHA and separate Internet control/WSS passed; final direct LAN WS interruption and the false completion_verified bit remain open, not fabricated success. - Retained: Local /update/info now uses boot-captured immutable image metadata rather than whole-image hashing on every progress poll. Status and WebSocket status/ping remain readable during local OTA; mutating commands remain inhibited. No authentication is enabled by the updater; it requires explicit auth-off readback before and after. @@ -1002,7 +1002,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp/src/LcdManagement.h:3 [UTF8-LF sha256=eb800ee4c334b22504f37bd841bda58a7562052df2c7226ff19bc23a454e652d; anchor=String lcdStatusJson()]`. - Target: `desktop/src/display.rs:7 [UTF8-LF sha256=9d73ae63aaa8a2bc4b824219c9cfab9f7924ae7566be7a9206c11b6344a2f18b; anchor=pub struct LcdObservation]`. - Target: `mobile/lib/peer_context.dart:302 [UTF8-LF sha256=c8602a12ccd3009028068aba091d46900c8aa0e345a4426ffe80acfb716362fc; anchor=bool lcdObservationReady(]`. -- Target: `firmware/esp/src/WebUi.h:2521 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function lcdObservation(]`. +- Target: `firmware/esp/src/WebUi.h:2538 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function lcdObservation(]`. - Retained: Complete actual donor source read through EOF. Adapted common PCF8574 0x27/0x3F discovery, 4-bit HD44780 wake/control bytes,16x2 ASCII row normalization/padding, desired frame cache and backlight bit mapping into a transport-independent production class. S3 owns dedicated GPIO15/16 hardware I2C so the confirmed AVR A4/A5 TM1637 and ISP pins remain untouched. - Omitted/replaced code: `Blocking50ms/4.5ms initialization, ignored expander return values and cache validity after failed writes`. Disposition: **replaced**. Reason: Initialization is a paced loop-owned state machine. Every expander write must ACK; no full frame/available status until all initialization and both rows complete. NACK revokes readiness, bounded retry reinitializes/replays current desired text. Missing modules cannot become initialized merely because initialize() returned. - Omitted/replaced code: `Flash-string overload and LCD clear/backlight/generic bus controls on all client surfaces; host-owned LCD prompt/priority/offline policy`. Disposition: **pending**. Reason: This slice implements standalone physical discovery/init/default cell/update text, finite REST presentation and exact completed-frame previews. It does not claim the full donor host presenter, raw I2C bridge, every app editor or USB LCD mutation parity. CompactI2c remains available for a future explicit nonconflicting AVR wiring/build profile after flash/RAM review. @@ -1024,7 +1024,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp/src/LcdManagement.h:3 [UTF8-LF sha256=eb800ee4c334b22504f37bd841bda58a7562052df2c7226ff19bc23a454e652d; anchor=String lcdStatusJson()]`. - Target: `desktop/src/display.rs:7 [UTF8-LF sha256=9d73ae63aaa8a2bc4b824219c9cfab9f7924ae7566be7a9206c11b6344a2f18b; anchor=pub struct LcdObservation]`. - Target: `mobile/lib/peer_context.dart:302 [UTF8-LF sha256=c8602a12ccd3009028068aba091d46900c8aa0e345a4426ffe80acfb716362fc; anchor=bool lcdObservationReady(]`. -- Target: `firmware/esp/src/WebUi.h:2521 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function lcdObservation(]`. +- Target: `firmware/esp/src/WebUi.h:2538 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function lcdObservation(]`. - Retained: Complete actual donor source read through EOF. Adapted common PCF8574 0x27/0x3F discovery, 4-bit HD44780 wake/control bytes,16x2 ASCII row normalization/padding, desired frame cache and backlight bit mapping into a transport-independent production class. S3 owns dedicated GPIO15/16 hardware I2C so the confirmed AVR A4/A5 TM1637 and ISP pins remain untouched. - Omitted/replaced code: `Blocking50ms/4.5ms initialization, ignored expander return values and cache validity after failed writes`. Disposition: **replaced**. Reason: Initialization is a paced loop-owned state machine. Every expander write must ACK; no full frame/available status until all initialization and both rows complete. NACK revokes readiness, bounded retry reinitializes/replays current desired text. Missing modules cannot become initialized merely because initialize() returned. - Omitted/replaced code: `Flash-string overload and LCD clear/backlight/generic bus controls on all client surfaces; host-owned LCD prompt/priority/offline policy`. Disposition: **pending**. Reason: This slice implements standalone physical discovery/init/default cell/update text, finite REST presentation and exact completed-frame previews. It does not claim the full donor host presenter, raw I2C bridge, every app editor or USB LCD mutation parity. CompactI2c remains available for a future explicit nonconflicting AVR wiring/build profile after flash/RAM review. @@ -1130,7 +1130,7 @@ Verdict: **scoped-improvement**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920 - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Target: `firmware/avr/BootMelody.cpp:37 [UTF8-LF sha256=fad1505f9cedc196236fc782ae2ec71a3c9fb8784659a1955affdf9e44137247; anchor=case kCueAttention:]`. - Target: `libraries/BoardCore/src/AttentionCues.h:13 [UTF8-LF sha256=02693199ab57f58a0531f46d8afa05ccd46dbd4c28b8db50b55bf5e4d1cff7b6; anchor=class Upload]`. - Target: `tools/test-audio.ps1:18 [UTF8-LF sha256=41500a0595fe030dd36f70175b56ee6f16ff62fe3bd1b2d9bf9bb29e94f90b30; anchor=Audio ยท]`. @@ -1164,7 +1164,7 @@ Verdict: **scoped-improvement**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920 - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Target: `firmware/avr/BootMelody.cpp:37 [UTF8-LF sha256=fad1505f9cedc196236fc782ae2ec71a3c9fb8784659a1955affdf9e44137247; anchor=case kCueAttention:]`. - Retained: Timer1 OC1A PB1/D9 hardware output without audio ISR; ten-step nonblocking ring queue; silent pauses; begin/stop/mute and active telemetry. - Retained: PCController already uses Timer1 hardware toggling; that is reuse, not a Pakar invention. @@ -1470,20 +1470,21 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `mobile/lib/pixel_corrections_editor.dart:115 [UTF8-LF sha256=7b307453c53c084f22bb5e3845b43ba56e34a83633447b36041c4b1facad64c5; anchor=class PixelCorrectionNumberControl]`. - Target: `mobile/lib/pixel_corrections_page.dart:18 [UTF8-LF sha256=731bf8e23114e7e3297efb2837244158633a79a49695e17e35276f4c592d5cb5; anchor=class PixelCorrectionsPage]`. - Target: `mobile/lib/pixel_groups_page.dart:16 [UTF8-LF sha256=f8ca0b6ce00982ffe4fca9dbaeafcaf38fa774e17a8f2c71b5ec4317fd8deb06; anchor=class PixelGroupsPage]`. -- Target: `assets/web/feature-workspaces.js:22 [UTF8-LF sha256=93f24fd4008ef69eb247dd02d084a531a04b1dffaa86d6b651df43b5b6c3f33a; anchor=function correctionsMatch(]`. +- Target: `assets/web/feature-workspaces.js:22 [UTF8-LF sha256=13a51897342b90e6d328d84da0c7272fd6f909fb84996de23a164bb48feb88fa; anchor=function correctionsMatch(]`. - Target: `assets/web/correction-preview.js:7 [UTF8-LF sha256=55aa374ed73c57a940a3b9fa65207250b70a306eb7982ecc68c0c23f10f1e72d; anchor=function createPixelCorrectionPreview(]`. - Target: `mobile/lib/pixel_correction_preview.dart:14 [UTF8-LF sha256=ab3c44bdf9bf29075e4fb825b9e2cf538097652e53582be12bd663e84c3cbb6d; anchor=class PixelCorrectionPreview]`. - Retained: Correction-editor owner read the complete donor. Adapted owned numeric drafts versus authoritative board state, invalid input retention and explicit commit. Live correction preview is a separate bounded board-owned lease; only Save writes persistent corrections. - Retained: Per-group count editor reuses the imported ControllerDialog and existing bounded numeric controls. Counts are local drafts with cumulative physical-address preview; explicit save uses same-peer revision fencing and effective-count readback, including normalized no-op saves. Invalid advertised layouts fail closed rather than silently using six/twelve. - Retained: The Web correction editor follows the actual Flutter correction-row enabled flag and the reread donor's local-edit/explicit-commit split. Per-rule checkboxes modify drafts only, disabled flags survive reordering and full saves, missing flags alone default true, malformed booleans are rejected, and exact saved readback compares enabled alongside kind/address/offset. Existing peer, capability and revision ownership remains shared. - Retained: Reread the complete actual PCController pwm_control at the unchanged inventoried hash and the complete existing Flutter pixel_correction_preview.dart. Adapted Flutter's explicit-only RAM lease, 280ms edit coalescing, exact source/base/owner readback, latency-adjusted renewal/expiry, original-route cleanup and no uncertain replay into a staged transport-injected Web controller. It reuses the canonical correction projection and owns no socket, renderer or persistence. UI integration, transport wiring and deployed behavior are not claimed. +- Retained: 2026-10-30 reread the complete unchanged PCController pwm_control and Flutter preview controller plus its actual foreground/active/save lifecycle slices. The canonical Web source already embedded the controller and preview-on-edit checkbox despite stale staged-only records. Acquisition/renewal/readback/release now use the original shared HTTP pin including connection generation, not a freshly admitted generic command. Hidden-document/pagehide cleanup and passive foreground/BFCache return adapt Flutter's foreground ownership; same-board route changes cannot redirect cleanup. Focused source/DOM tests cover captured-pin identity, lifecycle and disposal; actual browser/device/output and hidden workspace-panel acceptance remain open. - Omitted/replaced code: `PWM channels, duty-cycle write paths and output-specific labels`. Disposition: **not-applicable**. Reason: Pixel correction rules are ordered output-address mappings, not AVR PWM outputs; those hardware operations cannot be reused for this editor. - Test-code evidence: `mobile/test/pixel_corrections_editor_test.dart:145 [UTF8-LF sha256=ab953eb195c5f8ba3c086666c2f5a7444bccd7d2fb03433c2434d412a8aedeb4; anchor=void main()]`. - Test-code evidence: `mobile/test/pixel_groups_test.dart:102 [UTF8-LF sha256=94341dbc90467d273f5ad3f967a8d38e29738bec3c9509c9742cc25a18d34180; anchor=void main()]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:205 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Disabled state follows a reordered rule]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:206 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Disabled state follows a reordered rule]`. - Test-code evidence: `tests/web_correction_preview_test.mjs:24 [UTF8-LF sha256=86d135e460c8406eed4d031e3e97327b0d18a5219ea0d3237fea72876d2b6d32; anchor=No automatic preview or timers before explicit start]`. - Remaining: Network correction management is implemented; Flutter USB/BLE correction-editor configuration is not claimed. -- Remaining: The staged Web lease controller is not embedded or UI-wired. Explicit capability-gated controls, pinned shared transport/context authorization, foreground/panel/save/reload/disposal lifecycle and rendered acceptance remain open. Firmware currently has fenced HTTP/USB preview handlers but no named WebSocket preview command; do not invent a wire command or claim WebSocket preview support. No production lease or output acceptance from clock/transport doubles. +- Remaining: The current Web controller and capability-gated preview-on-edit checkbox are embedded and connected. Original-generation HTTP ownership and background/page lifecycle cleanup are source-tested; explicit workspace-panel hiding, rendered browser behavior and production lease/output acceptance remain open. Firmware currently has fenced HTTP/USB preview handlers but no named WebSocket preview command; do not invent one or claim WebSocket preview support. Opening/restoring the page is passive; edits may preview only when the existing checkbox is enabled. ### PCController: `mobile/lib/unified/relay_style.dart` @@ -1850,7 +1851,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp/src/LcdManagement.h:3 [UTF8-LF sha256=eb800ee4c334b22504f37bd841bda58a7562052df2c7226ff19bc23a454e652d; anchor=String lcdStatusJson()]`. - Target: `desktop/src/display.rs:7 [UTF8-LF sha256=9d73ae63aaa8a2bc4b824219c9cfab9f7924ae7566be7a9206c11b6344a2f18b; anchor=pub struct LcdObservation]`. - Target: `mobile/lib/peer_context.dart:302 [UTF8-LF sha256=c8602a12ccd3009028068aba091d46900c8aa0e345a4426ffe80acfb716362fc; anchor=bool lcdObservationReady(]`. -- Target: `firmware/esp/src/WebUi.h:2521 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function lcdObservation(]`. +- Target: `firmware/esp/src/WebUi.h:2538 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function lcdObservation(]`. - Retained: Complete actual donor source read through EOF. Preserved bounded transaction results, explicit master setup and timeout policy through the real S3 Wire1 adapter at100kHz/5ms transaction timeout. Transport interface isolates controller-specific registers instead of pretending AVR TWI can control an ESP32-S3 bus. - Omitted/replaced code: `AVR TWI register implementation, native AVR bridge receive buffer and host-proxied arbitrary I2C operations`. Disposition: **replaced**. Reason: The S3 uses actual native hardware I2C on separate pins, not the AVR connector already carrying non-I2C TM1637. A private adapter has no public arbitrary-bus mutation path. Copying AVR registers or enabling Wire on AVR A4/A5 would steal the display pins. - Omitted/replaced code: `Flash-string overload and LCD clear/backlight/generic bus controls on all client surfaces; host-owned LCD prompt/priority/offline policy`. Disposition: **pending**. Reason: This slice implements standalone physical discovery/init/default cell/update text, finite REST presentation and exact completed-frame previews. It does not claim the full donor host presenter, raw I2C bridge, every app editor or USB LCD mutation parity. CompactI2c remains available for a future explicit nonconflicting AVR wiring/build profile after flash/RAM review. @@ -1872,7 +1873,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp/src/LcdManagement.h:3 [UTF8-LF sha256=eb800ee4c334b22504f37bd841bda58a7562052df2c7226ff19bc23a454e652d; anchor=String lcdStatusJson()]`. - Target: `desktop/src/display.rs:7 [UTF8-LF sha256=9d73ae63aaa8a2bc4b824219c9cfab9f7924ae7566be7a9206c11b6344a2f18b; anchor=pub struct LcdObservation]`. - Target: `mobile/lib/peer_context.dart:302 [UTF8-LF sha256=c8602a12ccd3009028068aba091d46900c8aa0e345a4426ffe80acfb716362fc; anchor=bool lcdObservationReady(]`. -- Target: `firmware/esp/src/WebUi.h:2521 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function lcdObservation(]`. +- Target: `firmware/esp/src/WebUi.h:2538 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function lcdObservation(]`. - Retained: Complete actual donor source read through EOF. Preserved bounded transaction results, explicit master setup and timeout policy through the real S3 Wire1 adapter at100kHz/5ms transaction timeout. Transport interface isolates controller-specific registers instead of pretending AVR TWI can control an ESP32-S3 bus. - Omitted/replaced code: `AVR TWI register implementation, native AVR bridge receive buffer and host-proxied arbitrary I2C operations`. Disposition: **replaced**. Reason: The S3 uses actual native hardware I2C on separate pins, not the AVR connector already carrying non-I2C TM1637. A private adapter has no public arbitrary-bus mutation path. Copying AVR registers or enabling Wire on AVR A4/A5 would steal the display pins. - Omitted/replaced code: `Flash-string overload and LCD clear/backlight/generic bus controls on all client surfaces; host-owned LCD prompt/priority/offline policy`. Disposition: **pending**. Reason: This slice implements standalone physical discovery/init/default cell/update text, finite REST presentation and exact completed-frame previews. It does not claim the full donor host presenter, raw I2C bridge, every app editor or USB LCD mutation parity. CompactI2c remains available for a future explicit nonconflicting AVR wiring/build profile after flash/RAM review. @@ -1991,7 +1992,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Target: `desktop/src/ui/device_settings.rs:54 [UTF8-LF sha256=c087cbbde3bfc194b6002b10a3b63bb16ac4e253ef33d1a6f951ab2e566a42f6; anchor=fn avr_page(]`. - Target: `desktop/src/device_settings.rs:648 [UTF8-LF sha256=5bce7f14b9d6225d9aaa660838b8d07f7e14bda364c520a51f1c92e83d302ed6; anchor=pub fn finish_avr(]`. - Target: `firmware/esp/src/SceneStore.h:17 [UTF8-LF sha256=4877f4a54061ba25e69104055303781c84eb66f7f5eb49e3ec258370665a7bd2; anchor=template class SceneStore]`. @@ -2052,7 +2053,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Target: `desktop/src/ui/device_settings.rs:54 [UTF8-LF sha256=c087cbbde3bfc194b6002b10a3b63bb16ac4e253ef33d1a6f951ab2e566a42f6; anchor=fn avr_page(]`. - Target: `desktop/src/device_settings.rs:648 [UTF8-LF sha256=5bce7f14b9d6225d9aaa660838b8d07f7e14bda364c520a51f1c92e83d302ed6; anchor=pub fn finish_avr(]`. - Target: `libraries/BoardCore/src/PixelCorrections.h:12 [UTF8-LF sha256=2cffe251bb4f569b99cee3f3a6798f854c502cc983c57355e7947e40ce9f3c4d; anchor=bool enabled = true]`. @@ -2086,7 +2087,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp32s3/src/StatusRgb.h:162 [UTF8-LF sha256=a60111d37be51c4985e01d77821113fd0f97cd5df243e2e521b5ec3075b31b97; anchor=bool service(uint32_t now, Writer writer)]`. - Target: `desktop/src/status_rgb.rs:29 [UTF8-LF sha256=3dbe61cf121e44b14fe047427fbe9d0b8e60735baa445ad3116310560631965e; anchor=pub fn observe(]`. - Target: `mobile/lib/status_rgb.dart:52 [UTF8-LF sha256=458f867c97d38107b37fc399dfc55f1ad2f786ce5e236a9a9b2c048d0b4fbfd0; anchor=class StatusRgbPreview]`. -- Target: `firmware/esp/src/WebUi.h:2550 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function acceptStatusRgb(]`. +- Target: `firmware/esp/src/WebUi.h:2567 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function acceptStatusRgb(]`. - Retained: Full header/implementation read through EOF. Actual absolute elapsed/period evaluation, idempotent state ownership and already-scaled rendered RGB reporting adapted into the S3's board-owned semantic engine. Added bounded 300ms eased state transitions, explicit pin safety and driver-accepted output revision; no independent client-side animation reconstruction. - Retained: Native/Web/mobile now merge compact observed RGB revisions only for the selected exact board/boot. Duplicate/older/foreign revisions cannot overwrite newer RGB, renew command/hardware freshness or replace cells/layout. Complete status snapshots retain only newer same-peer RGB; peer changes discard it. Selected transport capabilities gate settings with no silent Wi-Fi fallback, and writes require saved ACK plus exact persisted readback rather than a local preview. - Omitted/replaced code: `PwmController/EEPROM/StatusProfileAddress dependencies and sixteen-bit phase clock`. Disposition: **replaced**. Reason: Those target AVR RGB PWM wiring and EEPROM allocation, not the identified S3 addressable pixel. Existing S3 persisted configuration owns enable/brightness, writer acceptance owns reported output, and the 32-bit elapsed timer advances without per-loop phase drift. @@ -2122,7 +2123,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `firmware/esp32s3/src/StatusRgb.h:242 [UTF8-LF sha256=a60111d37be51c4985e01d77821113fd0f97cd5df243e2e521b5ec3075b31b97; anchor=static uint8_t scale(]`. - Target: `desktop/src/status_rgb.rs:2 [UTF8-LF sha256=3dbe61cf121e44b14fe047427fbe9d0b8e60735baa445ad3116310560631965e; anchor=clients never synthesize]`. - Target: `mobile/lib/status_rgb.dart:9 [UTF8-LF sha256=458f867c97d38107b37fc399dfc55f1ad2f786ce5e236a9a9b2c048d0b4fbfd0; anchor=Color? statusRgbColor(]`. -- Target: `firmware/esp/src/WebUi.h:2549 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function statusRgbOutput]`. +- Target: `firmware/esp/src/WebUi.h:2566 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function statusRgbOutput]`. - Retained: Full original source read through EOF. Actual unsigned byte-exact scale(value, level) and interpolate(from, to, phase) arithmetic copied into the S3 semantic onboard-pixel engine, independent of the GPIO4 matrix. - Omitted/replaced code: `phaseDeadline distributing 64 phases in a modulo-16-bit AVR clock`. Disposition: **replaced**. Reason: S3 evaluates the present phase directly from uint32 elapsed milliseconds rather than scheduling 64 deadline steps. Late service does not slow the animation; native tests cover real production arithmetic and millis wrap, not optical output. - Test-code evidence: `tests/s3_status_rgb_test.cpp:69 [UTF8-LF sha256=f48af12963f643feca43b77ed5edd181e22981afb761305cf947d5ad053fa6f7; anchor=Already-scaled output bytes]`. @@ -2243,7 +2244,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Retained: Reread complete donor source through EOF. Adapt MCU-owned persistent Silent bit independent of host/Windows notification audio, capability-acknowledged controls, explicit unknown/pending/verified states and full-record preservation. Native Preferences Board page uses existing PCController GET/SET/GET with real AVR ACK and persistent readback over the selected fenced HTTP or USB owner only; Web and Flutter Preferences use the same living contract. No unsupported buzzer is invented, no automatic uncertain mutation replay, and unchanged persisted flags skip EEPROM writes. - Omitted/replaced code: `Full board/host/both/none mirroring routes, runtime overrides, OS backend/executable resolution and watched app configuration`. Disposition: **pending**. Reason: Reuse the known/unknown/pending/verified board-setting ownership, not an unimplemented host audio backend. Actual host routing parity needs independent implementation and acoustic acceptance; this change must not mute Windows notifications by accident. - Test-code evidence: `tests/tone_player_test.cpp:46 [UTF8-LF sha256=d1d890f6ead81d22702eb685ae710935bc7c007af5f97236454b851a3f5adc42; anchor=const auto beforeMute]`. @@ -2512,7 +2513,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `desktop/src/firmware_progress.rs:211 [UTF8-LF sha256=11188ec3c9bc7b89e76b94e5412f0e689fa656e5a636d4964136c2236aabbe31; anchor=pub fn observed(]`. - Target: `mobile/lib/firmware_progress.dart:9 [UTF8-LF sha256=c384ea707aee45a2c6e8faa7bfdaadadfc3d8b3a0b92f46ddce4d085edded464; anchor=class FirmwareProgress]`. -- Target: `firmware/esp/src/WebUi.h:2701 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function firmwareUpdateObservation(s)]`. +- Target: `firmware/esp/src/WebUi.h:2718 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function firmwareUpdateObservation(s)]`. - Retained: Adapt actual explicit measured stage counters, indeterminate non-transfer stages, separate verification/completion and terminal state handling. Rust retains external board update/local OTA state in HTTP/WS/USB DTOs; Flutter consumes the existing status stream, and Web renders that same source. No transfer 100 percent is treated as completed flashing. - Retained: 2026-10-29: reread the complete current donor and tests. Redesign the actual Flutter progress consumer using the imported Workspace semantic icon/card/badge surfaces. Show exact stage-local bytes/percentage, distinguish Sending from Programming and explicit verified completion from pending recovery. Unmeasured verification/reboot remains indeterminate; no fabricated ETA or stage history. Add compact/wide, light/dark, RTL and large-text bounds fixtures; installed/device progress evidence remains a separate gate. - Omitted/replaced code: `Remaining donor mechanisms outside this delivery slice`. Disposition: **pending**. Reason: This slice does not port the donor's per-operation milestone toast tracker, Windows taskbar COM ordering or terminal OSC progress presenter. Existing native notifications remain, but complete progress-notification/OS presentation parity is pending. @@ -2904,7 +2905,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. Original-byte SHA-256: `de67f2ac9dd8037e354b98227616ed8c207379dbc8205692587bc07a6392be83`. - Target: `assets/web/device-settings.js:165 [UTF8-LF sha256=28b490c94a63c0b55df4cac22405b02d9ef43725ee08d5e9e3cc418ae8df5492; anchor=function panelToggle(]`. -- Target: `assets/web/feature-workspaces.js:180 [UTF8-LF sha256=93f24fd4008ef69eb247dd02d084a531a04b1dffaa86d6b651df43b5b6c3f33a; anchor=function reveal(target)]`. +- Target: `assets/web/feature-workspaces.js:180 [UTF8-LF sha256=13a51897342b90e6d328d84da0c7272fd6f909fb84996de23a164bb48feb88fa; anchor=function reveal(target)]`. - Target: `assets/web/device-settings.js:166 [UTF8-LF sha256=28b490c94a63c0b55df4cac22405b02d9ef43725ee08d5e9e3cc418ae8df5492; anchor=function renderPanelMenu(]`. - Target: `assets/web/workspace-studio.js:87 [UTF8-LF sha256=c5c4b999f9fb7ca6011b9193a1ded10ed293bba8b53d9c861ad1ea4c108a15f4; anchor=for(const[id,label]of pages)]`. - Target: `assets/web/studio.css:105 [UTF8-LF sha256=4d87d4cc97b3a53b2144912cd0c123ebc21b9b7677bdb02e6901a6c695e36e22; anchor=--square-size:34px]`. @@ -2916,7 +2917,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Omitted/replaced code: `CardLayoutCopy localization and Lucide Check/ChevronDown/Eye/EyeOff/GripVertical/RotateCcw toolbar glyphs`. Disposition: **pending**. Reason: Show/Hide/Reset, collapse and sidebar glyph/localized accessible-name consumers are now adapted with the established vector catalog. Remaining edit/reorder controls, all CardLayoutCopy consumers and their keyboard/pointer focus behavior are not certified by this pass; no React/Lucide runtime was added. - Omitted/replaced code: `React generic component props and ReactPointerEvent/CSSProperties wrappers`. Disposition: **replaced**. Reason: The ESP serves a standalone embedded document, not the donor React runtime. Existing live DOM cards retain their handlers when settings cards are reparented; no duplicate React state is introduced. - Test-code evidence: `tests/web_control_presentation_test.mjs:74 [UTF8-LF sha256=f563ad7b87d95fdb08b84737436774bfc4d21a709678007287d25706f05c2272; anchor=Collapsed rail actions retain localized accessible names]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:103 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Injected navigation must not be followed by a second targetless fallback]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:104 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Injected navigation must not be followed by a second targetless fallback]`. - Test-code evidence: `tests/web_control_presentation_test.mjs:79 [UTF8-LF sha256=f563ad7b87d95fdb08b84737436774bfc4d21a709678007287d25706f05c2272; anchor=assert.equal(menu.children[0].getAttribute('aria-checked'),'true')]`. - Test-code evidence: `tests/interface_settings_test.mjs:123 [UTF8-LF sha256=102d6c411b732bad8106dd09358da3df3989d1140aa77c87a884c8072c66c6f3; anchor=Capability loss must override stored panel visibility]`. - Remaining: Complete edit-mode panel ordering, remaining edit/reorder icon/localization consumers and pointer/keyboard ownership tests. The named menu/rail/collapse glyphs are implemented; source/HTTP doubles and browser fixtures are not physical acceptance. @@ -2979,7 +2980,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O - Target: `mobile/lib/main.dart:1052 [UTF8-LF sha256=814e5944b0f27d21f2005ff4bfa8e391dc5721435e25f9c40ccf2c934090a7db; anchor=Future _command]`. - Target: `libraries/BoardCore/src/DeviceContext.h:25 [UTF8-LF sha256=d1fe9e5a3663b13017ea61d251b6bc314ce91b2cb43b8c8b9c5308fe5fa73f1c; anchor=inline uint16_t features(]`. - Target: `firmware/esp/application.ino:2471 [UTF8-LF sha256=a607abb53d7834663853f2adb45286361d9d5b1cf82edb0d18ee11c9d9a74c41; anchor=if(BoardCore::Context::pixelEvents(available))]`. -- Target: `firmware/esp/src/WebUi.h:2512 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function peerAvailability(]`. +- Target: `firmware/esp/src/WebUi.h:2529 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function peerAvailability(]`. - Retained: Actual connected AND have_status AND advertised-capability conjunction adapted to selected-peer fresh manifests. No feature inference from hostname, pixel count, catalog, defaults or online alone. - Retained: Reread the complete unchanged availability donor and tests for the table live-preview regression. Shared Context::pixelEvents now requires actual Network plus Leds service availability for both compiled roles, without requiring AVR acknowledgement. The same predicate owns feature advertisement, subscription admission and publication; no-driver and network-disabled builds cannot advertise or start pixel events. Existing authorized-listener-only latest-frame coalescing and backpressure remain unchanged. Both role host fixtures and source integration guards passed; live device subscription and optical acceptance remain separate. - Retained: Reread the complete unchanged donor and actual Flutter peer parser/menu/tab consumers for missing Pixel corrections: the known-feature allowlist now retains the explicit pixel-corrections advertisement. Unsupported or mismatched-owner manifests still cannot expose it; existing linked Diagnostics/Corrections tabs are reused rather than duplicated. Actual overflow navigation fixtures assert supported/unsupported visibility and zero board writes. @@ -3014,7 +3015,7 @@ Verdict: **equivalent-behavior**. Revision: `b0111ae0c80dc34149ea1044de7dd548892 Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. Original-byte SHA-256: `7a3e955ddc771cf27f9e545c11ea992a1342a7ed5eaeba9d9a5b95d00dacd2bc`. -- Target: `firmware/esp/src/WebUi.h:2473 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function workspaceSettingsRecord]`. +- Target: `firmware/esp/src/WebUi.h:2490 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function workspaceSettingsRecord]`. - Retained: Completely read actual allowlisted normalized local-preferences and unavailable-storage behavior; adapt bounds/type validation and storage-disabled retention to passive board/application Web workspaces. - Omitted/replaced code: `Full donor quick-header action/catalog UI`. Disposition: **pending**. Reason: This reuses normalization/persistence, not every quick-header control; individual capability-gated donor controls need separate mapping. - Test-code evidence: `tests/web_workspace_test.mjs:115 [UTF8-LF sha256=e35df2215cf2802e9e58896204d4c44dbb12225411a7c511808f47af9679d7cf; anchor=Disabled browser storage still retains this session workspace]`. @@ -3038,7 +3039,7 @@ Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. O Verdict: **parity-gap**. Revision: `b0111ae0c80dc34149ea1044de7dd5488920301b`. Original-byte SHA-256: `f600267bf09d925eaf9e5cc3d752574a0a3fbc46350782c614440300c08799e4`. - Target: `assets/web/frame-stream.js:9 [UTF8-LF sha256=3d0ab90616b173570e5618be76aded339754caa92961868a1d9b43a02e3c6d90; anchor=function createFrameStream]`. -- Target: `firmware/esp/src/WebUi.h:3794 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function readStreamPolicy]`. +- Target: `firmware/esp/src/WebUi.h:3811 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function readStreamPolicy]`. - Retained: Full source read through EOF. Actual injected clock, generation admission, one scheduled callback, cancellation and disposal structure adapted to the mechanically embedded latest-frame Web stream. - Retained: Stale callbacks check generation before clearing the timer handle, strengthening the donor against disarming a replacement owner. Observed board/boot and exact socket ownership replace build/name-only identity for this bounded slice. - Omitted/replaced code: `pendingStatus history queue and applyStatusFrameBatch ordered metrics/error reducer`. Disposition: **pending**. Reason: All status arrivals are useful for telemetry/history, but stale LED actuations must not be replayed. This latest-only send scheduler does not implement the donor telemetry reducer; retain it as separate useful work. @@ -3509,7 +3510,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `desktop/src/ui/preferences.rs:262 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=fn board_controls(]`. - Target: `mobile/lib/api.dart:2109 [UTF8-LF sha256=bbb407cc65ccd54e10d7a21328d07831ce5fa3eff70eebe99a6a10b3815257e8; anchor=Future boardSound(]`. - Target: `mobile/lib/board_sound_preferences.dart:10 [UTF8-LF sha256=888e518c1a85ff594b6c4c778f2eb770a4cbcad3a1d53d3defea19b5e226dc5d; anchor=class BoardSoundPreferences]`. -- Target: `firmware/esp/src/WebUi.h:3551 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=async function boardSoundTransaction(]`. +- Target: `firmware/esp/src/WebUi.h:3568 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=async function boardSoundTransaction(]`. - Retained: Reread all 1280 lines through EOF. Prior authoritative overview/capability/front-panel adaptation remains; shared dropdown dependency is now imported, but full typed board settings and ACK consumers remain pending. - Retained: Numeric display controls are independent of Text; peer title follows acknowledged name and lost capabilities cancel Table work. - Retained: Reread complete donor source through EOF. Adapt MCU-owned persistent Silent bit independent of host/Windows notification audio, capability-acknowledged controls, explicit unknown/pending/verified states and full-record preservation. Native Preferences Board page uses existing PCController GET/SET/GET with real AVR ACK and persistent readback over the selected fenced HTTP or USB owner only; Web and Flutter Preferences use the same living contract. No unsupported buzzer is invented, no automatic uncertain mutation replay, and unchanged persisted flags skip EEPROM writes. @@ -3596,7 +3597,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `desktop/src/ui/preferences.rs:364 [UTF8-LF sha256=38bda5597ef69c27761de2bfc820e2d507c8fe29353d3e1f95c118a477d22448; anchor=let action_height = super::control_density::height(ui).max(dialog::ACTION_HEIGHT);]`. - Target: `desktop/src/ui/cell_table.rs:725 [UTF8-LF sha256=a895f275243c9079783aa7f0165bac1d21f692e84b30f8aaeed4fbcc52cf8a19; anchor=fn manager_selector(]`. -- Target: `firmware/esp/src/WebUi.h:183 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=/* Fixed manager slots:]`. +- Target: `firmware/esp/src/WebUi.h:183 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=/* Fixed manager slots:]`. - Target: `desktop/src/ui/effect_controls.rs:66 [UTF8-LF sha256=da148d2876de05674cc876ed167df5518bb294698090ec5d3fd5a6ad39587dfc; anchor=pub fn mode_picker(]`. - Target: `desktop/src/ui/panel_details.rs:161 [UTF8-LF sha256=d52b713fbf32ae3f9cf0c550f0ff172d2bc5450eeb985ab8a0ce1e0a7edd2d0d; anchor=pub fn correction_rules(]`. - Target: `desktop/src/ui/panel_details.rs:348 [UTF8-LF sha256=d52b713fbf32ae3f9cf0c550f0ff172d2bc5450eeb985ab8a0ce1e0a7edd2d0d; anchor=pub fn network(]`. @@ -3814,7 +3815,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `desktop/src/ui/shell.rs:1653 [UTF8-LF sha256=015877d9b262b596d4e27fdddcbd03a42c8c1e1cbe2b15f46632a88bce7ccce8; anchor=let firmware_progress = self.firmware_observation().filter(|p| p.active);]`. - Target: `desktop/src/ui/connection_controls.rs:90 [UTF8-LF sha256=02bbb46d280c606868f0f18220cb092c0dca2e07f9b06aa31bee1e4f4625ec65; anchor=pub fn draw(]`. - Target: `docs/CONNECTION-CONTROLS.md:1 [UTF8-LF sha256=002ee046e9c206a4cc241ad2b9033971b4933959d8e14f43958848403879f21d; anchor=# Front-panel transport dropdowns]`. -- Target: `firmware/esp/src/WebUi.h:2549 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function statusRgbOutput]`. +- Target: `firmware/esp/src/WebUi.h:2566 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function statusRgbOutput]`. - Target: `desktop/src/status_rgb.rs:46 [UTF8-LF sha256=3dbe61cf121e44b14fe047427fbe9d0b8e60735baa445ad3116310560631965e; anchor=pub fn retain(]`. - Target: `mobile/lib/status_rgb.dart:52 [UTF8-LF sha256=458f867c97d38107b37fc399dfc55f1ad2f786ce5e236a9a9b2c048d0b4fbfd0; anchor=class StatusRgbPreview]`. - Retained: Current complete source read through EOF independently by the status/front-panel and network/UI agents; selected target changes reviewed again during evidence integration. Actual per-item hide context menus, persistent visibility choices, bar-level restore menu and small truncating message labels remain adapted. Transport controls remain usable offline without claiming hardware readiness. @@ -3866,8 +3867,8 @@ Verdict: **scoped-improvement**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cd Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. Original-byte SHA-256: `410d274f51e5e7db7ce81582d36166a97240b097e993cec5fee8707a95183e2f`. - Target: `mobile/lib/output_panel.dart:27 [UTF8-LF sha256=3cf8895bbbdfc82cb7f4c12ed8e1895623099975722753d5dc722d3eb7ebe9c3; anchor=class OutputPanel]`. -- Target: `assets/web/feature-workspaces.js:108 [UTF8-LF sha256=93f24fd4008ef69eb247dd02d084a531a04b1dffaa86d6b651df43b5b6c3f33a; anchor=function diagnosticWorkspace(value)]`. -- Target: `web/index.html:2472 [UTF8-LF sha256=50951b137bc42eccc73d953ecf599c2d28d31ce2c041c0539b96d5ad3c747686; anchor=function workspaceDiagnosticDraft()]`. +- Target: `assets/web/feature-workspaces.js:108 [UTF8-LF sha256=13a51897342b90e6d328d84da0c7272fd6f909fb84996de23a164bb48feb88fa; anchor=function diagnosticWorkspace(value)]`. +- Target: `web/index.html:2489 [UTF8-LF sha256=aa518a96eea2dd7d787cb0a31d5191c78886e2e31605eda64458a0cea728835d; anchor=function workspaceDiagnosticDraft()]`. - Target: `mobile/test/output_panel_test.dart:411 [UTF8-LF sha256=b75b25f46b391a84c0400f08361c4c520e2fda547e95f8b9030078f7f281e317; anchor=Output order is bounded, durable and independent of table selection]`. - Target: `mobile/lib/table_workspace.dart:13 [UTF8-LF sha256=02445683146ff2b3bdca50bfa8d1aa1dedb94261c361613fdb545e7ca4f7c83e; anchor=class TableWorkspace]`. - Target: `mobile/lib/main.dart:897 [UTF8-LF sha256=814e5944b0f27d21f2005ff4bfa8e391dc5721435e25f9c40ccf2c934090a7db; anchor=Future _saveWorkspaces()]`. @@ -3891,7 +3892,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Omitted/replaced code: `All donor profile dialog/tab presets, media-specific panels and workspace action parity`. Disposition: **pending**. Reason: Stable identity and transient-layout preservation are a scoped adaptation, not all donor profile editor/defaults/import-export UI. Media-only panels remain outside this controller; generic profile actions still need exact comparisons. - Omitted/replaced code: `Unsaved native privileged network/cloud/AVR form drafts`. Disposition: **pending**. Reason: They remain intentionally invalidated on peer revocation until durable public-only patches can be rebased against fresh baseline/secret ownership. General per-peer workspace controls and safe presentation drafts are persisted; this is not all editor-draft parity. - Test-code evidence: `mobile/test/workspace_lifecycle_test.dart:528 [UTF8-LF sha256=537941477dab0a2460cf42aab9220a7baf8d1aecf36eb140b21179674985071e; anchor=Workspace follows board identity]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:320 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Live observations do not trigger durable writes]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:321 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Live observations do not trigger durable writes]`. - Test-code evidence: `tests/web_workspace_test.mjs:124 [UTF8-LF sha256=e35df2215cf2802e9e58896204d4c44dbb12225411a7c511808f47af9679d7cf; anchor=A not-yet-attached feature owner preserves the existing scoped draft]`. - Test-code evidence: `desktop/src/capabilities.rs:442 [UTF8-LF sha256=fe68fb6d4d5262079bae60446dd4dfbfc8f69ecce59cd7b12084f7d2cf6eb2a7; anchor=fn presentation_retains_only_prior_acks_without_reviving_live_authority]`. - Test-code evidence: `desktop/src/capabilities.rs:504 [UTF8-LF sha256=fe68fb6d4d5262079bae60446dd4dfbfc8f69ecce59cd7b12084f7d2cf6eb2a7; anchor=fn measured_panel_height_preserves_scroll_only_for_same_board_panel_and_width]`. @@ -3968,7 +3969,7 @@ Verdict: **equivalent-behavior**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1c Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. Original-byte SHA-256: `ba2d7a35e2f887ec556b681cca24aaa6f263295208cbc80678bc248b61949845`. -- Target: `firmware/esp/src/WebUi.h:2458 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function createWorkspaceStorage]`. +- Target: `firmware/esp/src/WebUi.h:2475 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function createWorkspaceStorage]`. - Target: `assets/web/device-settings.js:93 [UTF8-LF sha256=28b490c94a63c0b55df4cac22405b02d9ef43725ee08d5e9e3cc418ae8df5492; anchor=function settingsObserve]`. - Target: `assets/web/workspace-studio.js:9 [UTF8-LF sha256=c5c4b999f9fb7ca6011b9193a1ded10ed293bba8b53d9c861ad1ea4c108a15f4; anchor=function studioRoute(]`. - Retained: Completely reread matching actual donor. Import/adapt readStoredJson/persistJson pending-map/timer/pagehide and per-surface scroll patterns into immutable board_id+application.id workspace storage. Selection/find/focus, presentation/panels, public drafts, settings navigation and scroll restore passively; equal writes skip, blocked storage retains in-memory state, and changed fresh settings keep their conflict baseline. @@ -3985,7 +3986,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `assets/themes/appearance.js:4 [UTF8-LF sha256=62a7ebba994ad44f4e2d647bb97684aac9b563104f3f707b43573289e514ecdd; anchor=export function mergeAppearance]`. - Target: `tools/generate-web-appearance.mjs:33 [UTF8-LF sha256=e57a615bf5134b718d6df7b644e56faced0c0ef73e8662cf8cb06c05e23e59b4; anchor=replaceBlock('// BEGIN SHARED APPEARANCE']`. -- Target: `firmware/esp/src/WebUi.h:10 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=// BEGIN SHARED APPEARANCE]`. +- Target: `firmware/esp/src/WebUi.h:10 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=// BEGIN SHARED APPEARANCE]`. - Retained: Fully reread current source through EOF. The five previously adapted helpers remain in the target: mergeAppearance, resolvedAccent, resolvedAppearanceTheme, accentForeground and paletteName. Existing theme/palette/accent host resolution and luminance semantics remain; newer animation/density/font preference fields and font CSS helpers are explicitly pending, not claimed imported. - Retained: Generated into the shipped WebUi.h with the shared palette asset; --check rejects stale embedding. Browser preferences dialog validates theme/palette/accent, protects drafts, handles storage failure and cross-tab/System events without device writes or repetitive identical storage writes. - Omitted/replaced code: `ui_animation_mode, ui_control_density, ui_font_family, monospace_font_family merge fields; ControlDensity/controlDensityHeight 24/28/32/36 geometry; uiFontCss and monoFontCss`. Disposition: **pending**. Reason: New current donor behavior was fully read during mobile-network build preflight. Existing embedded target does not consume these client preferences and does not bundle PealayerUbuntu/PealayerHack; copying their font names would imply unavailable assets. Add actual shared settings/asset support and cross-client tests before claiming parity. @@ -4050,7 +4051,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. Original-byte SHA-256: `8c90f7a85286efada6d5a1e24212a03dd1ae14e51bea1767f8d195a538ec8f80`. -- Target: `assets/web/feature-workspaces.js:366 [UTF8-LF sha256=93f24fd4008ef69eb247dd02d084a531a04b1dffaa86d6b651df43b5b6c3f33a; anchor=async function reloadCorrections(]`. +- Target: `assets/web/feature-workspaces.js:383 [UTF8-LF sha256=13a51897342b90e6d328d84da0c7272fd6f909fb84996de23a164bb48feb88fa; anchor=async function reloadCorrections(]`. - Target: `web/modules/components.js:135 [UTF8-LF sha256=200e38d3a70594f6f2463b03bc74df53cc10e17e8d2264c7851c200d9beff7d4; anchor=function dialog(]`. - Target: `assets/web/application-utilities.js:116 [UTF8-LF sha256=20744bfcfc0968df0205a46aeb3bdd513b205f0f91796b168dd99dcb16fdbbf1; anchor=initialFocus:search]`. - Target: `assets/web/pixel-groups.js:58 [UTF8-LF sha256=24abe18fbf1f11fe248f2f1ac5fe6b7149014be1290fae0f8b3bef59c256e617; anchor=async function reloadGroups(]`. @@ -4061,9 +4062,9 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Omitted/replaced code: `React/Ant Design Modal runtime`. Disposition: **replaced**. Reason: Reuse Pakar's existing native HTML dialog with focus restoration and shared branding rather than loading a duplicate framework into the onboard build. - Omitted/replaced code: `Effect-group name/original_name save and media-group mutation`. Disposition: **not-applicable**. Reason: This correction reload reads saved board configuration; it must not mutate media effect groups. - Omitted/replaced code: `EffectIconPicker searchable icon presets and live group-name/glyph preview`. Disposition: **pending**. Reason: Generic icon-picker behavior remains useful for configurable app elements. This narrow reload dialog has no editable icon/name and does not imply that picker has been imported or its dependencies reviewed. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:117 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Only one confirmation may own the editor]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:118 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Only one confirmation may own the editor]`. - Test-code evidence: `tests/web_dialog_test.mjs:53 [UTF8-LF sha256=63745a228e1e9748f7d8eb89c7f1a3eaa4f4e1e5d34b6fe5f6805c03e668552d; anchor=Only one asynchronous action owns the dialog]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:389 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Only one group confirmation owns the draft]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:390 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Only one group confirmation owns the draft]`. - Remaining: 2026-10-27 desktop browser verification reproduced approval losing focus while Reload was disabled. Both correction and group confirmations now retain the existing async dialog owner through the read; delayed-read tests verify the trigger is enabled before close and stale approval stays inert. Actual correction Reload restores focus, Escape preserves drafts, and Cancel receives initial focus. Expanded map/filter/cursor numbering and persisted filter were also inspected. Phone/tablet/Persian RTL, real board reads and group-dialog rendered acceptance remain open. ### Pealayer: `web_ui/src/components/HeaderBar.tsx` @@ -4073,9 +4074,9 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `tools/generate-branding.mjs:3 [UTF8-LF sha256=816544b2525d3c9210a586b8c2c5d59ed6c51fab8ca4bda27fbf2edbdd451367; anchor=Pakar embeds it for the standalone ESP surface]`. - Target: `mobile/lib/header_controls.dart:17 [UTF8-LF sha256=fdbae404068b75de261d1add7d5768e1b6844272ddfe4edb1b92b338f6cf4f87; anchor=class HeaderLayout]`. - Target: `mobile/lib/main.dart:767 [UTF8-LF sha256=814e5944b0f27d21f2005ff4bfa8e391dc5721435e25f9c40ccf2c934090a7db; anchor=Future _openConnection()]`. -- Target: `firmware/esp/src/WebUi.h:399 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=]`. +- Target: `firmware/esp/src/WebUi.h:399 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=]`. - Target: `docs/BRANDING-PARITY.md:60 [UTF8-LF sha256=0bfa8122dc9d6034551304f2fed472ddebcff170e14a23f63011177aab75d2d3; anchor=## Explicit unfinished useful code and reasons]`. -- Target: `firmware/esp/src/WebUi.h:3061 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function renderApplicationIdentity]`. +- Target: `firmware/esp/src/WebUi.h:3078 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function renderApplicationIdentity]`. - Target: `assets/web/device-settings.js:120 [UTF8-LF sha256=28b490c94a63c0b55df4cac22405b02d9ef43725ee08d5e9e3cc418ae8df5492; anchor=function settingsCanClose()]`. - Target: `docs/INTERFACE-CONTRACT.md:8 [UTF8-LF sha256=37a0aec859267e0fd62b546ffc044eaa02ae04d2f9a298c5d94a5c24c803cb1b; anchor=## One catalog, distinct transport and platform adapters]`. - Retained: Actual resolved-artwork img/alt binding adapted to standalone header/login, replacing diamond and font fallback. @@ -4099,7 +4100,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `mobile/lib/pixel_corrections_editor.dart:115 [UTF8-LF sha256=7b307453c53c084f22bb5e3845b43ba56e34a83633447b36041c4b1facad64c5; anchor=class PixelCorrectionNumberControl]`. - Target: `assets/web/pixel-groups.js:44 [UTF8-LF sha256=24abe18fbf1f11fe248f2f1ac5fe6b7149014be1290fae0f8b3bef59c256e617; anchor=function create(options)]`. -- Target: `assets/web/feature-workspaces.js:282 [UTF8-LF sha256=93f24fd4008ef69eb247dd02d084a531a04b1dffaa86d6b651df43b5b6c3f33a; anchor=function stepped(]`. +- Target: `assets/web/feature-workspaces.js:299 [UTF8-LF sha256=13a51897342b90e6d328d84da0c7272fd6f909fb84996de23a164bb48feb88fa; anchor=function stepped(]`. - Target: `assets/web/command-transport.js:63 [UTF8-LF sha256=829ced127abe461595384f58822a18dc1e8e5388a6907bca945d566d53fe1e73; anchor=if(path==='/api/led/diagnostic')]`. - Target: `assets/web/studio.css:122 [UTF8-LF sha256=4d87d4cc97b3a53b2144912cd0c123ebc21b9b7677bdb02e6901a6c695e36e22; anchor=.studio .mapping-pixel>.mapping-dot]`. - Target: `assets/web/controller-copy.json:300 [UTF8-LF sha256=441c7b489b0e5b683da61cd667f9251d3542e0be57b1abb2e0780497455a0b22; anchor=Rule preview]`. @@ -4118,10 +4119,10 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Omitted/replaced code: `React/CSS execution and media-value callers`. Disposition: **replaced**. Reason: Flutter or Pakar's canonical DOM owns rendering. The bounded-control interaction is adapted rather than embedding a second framework; pixel addresses and signed offsets replace media-value domains. - Omitted/replaced code: `Custom fine/coarse modifier step configuration and clipboard context menu`. Disposition: **pending**. Reason: The pixel-count editor uses bounded integer one-pixel steps and explicit reset. Donor custom modifier steps/clipboard menu were read but are not yet imported; this is a scoped sizing feature, not complete NumericValueControl parity. - Test-code evidence: `mobile/test/pixel_corrections_editor_test.dart:145 [UTF8-LF sha256=ab953eb195c5f8ba3c086666c2f5a7444bccd7d2fb03433c2434d412a8aedeb4; anchor=void main()]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:406 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Retired group row callbacks cannot mutate replacement draft]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:407 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Retired group row callbacks cannot mutate replacement draft]`. - Test-code evidence: `tests/web_command_transport_test.mjs:59 [UTF8-LF sha256=14e3581c9d9289f2059c9f23f4de5bcd4ff803e813f7c9db062ca0408e4b671f; anchor=captured.composite,'overlay']`. - Test-code evidence: `tests/web_control_presentation_test.mjs:96 [UTF8-LF sha256=f563ad7b87d95fdb08b84737436774bfc4d21a709678007287d25706f05c2272; anchor=Pixel circles retain fixed square geometry]`. -- Test-code evidence: `tests/web_feature_workspaces_test.mjs:41 [UTF8-LF sha256=0ee5cabce984e6f4e39fcdbe057e65897559a1f67dc1a35e010dab929ed691ca; anchor=Rule window includes its prefix, not later rules]`. +- Test-code evidence: `tests/web_feature_workspaces_test.mjs:42 [UTF8-LF sha256=e02d06ce8ffcd53f00ecbb4524396aebe31d9035bb6e575b10fc47cca4eb1a7a; anchor=Rule window includes its prefix, not later rules]`. - Remaining: Rust correction editor does not yet expose these new per-row/preview controls; no cross-client parity claimed. ### Pealayer: `web_ui/src/components/PlaybackButton.tsx` @@ -4129,7 +4130,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. Original-byte SHA-256: `10b2c97e2b85d1f5390790992b53a8250dc49847ce0c4b1679f5928e30b9fe5a`. - Target: `assets/web/application-utilities.js:37 [UTF8-LF sha256=20744bfcfc0968df0205a46aeb3bdd513b205f0f91796b168dd99dcb16fdbbf1; anchor=function setControlCaption(]`. -- Target: `web/index.html:3257 [UTF8-LF sha256=50951b137bc42eccc73d953ecf599c2d28d31ce2c041c0539b96d5ad3c747686; anchor=function renderAssignmentTools(]`. +- Target: `web/index.html:3274 [UTF8-LF sha256=aa518a96eea2dd7d787cb0a31d5191c78886e2e31605eda64458a0cea728835d; anchor=function renderAssignmentTools(]`. - Retained: The Web owner fully read the actual canonical Pealayer component. Preserve its authoritative-snapshot action meaning, disabled unknown/unavailable state and matching icon/label/accessibility rather than optimistic click-state toggling. Existing cell ACK/capability gates remain authoritative; state-caption refresh uses the existing semantic state model and stable label slot. Selection by lost/won identity remains correct even when a user changes the configured RGB color. - Retained: Only canonical Pealayer web_ui/src/styles.css lines 77-102 and 521-552 were inspected as styling dependencies, SHA256 2d08f0129a28e29b55a137c708b9296d5282bd0aaffb6c2fdba6b9d5cf16462d. Fixed borders, optical glyph alignment and restrained tonal states were adapted; the whole stylesheet is not certified read. - Omitted/replaced code: `Play/Pause media command and React/Ant component runtime`. Disposition: **not-applicable**. Reason: The board application has no media player; only authoritative state and visual/action identity are adapted into its existing DOM model. @@ -4146,8 +4147,8 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `mobile/lib/device_settings.dart:413 [UTF8-LF sha256=0c10e5c712bae2b4fe2f706326115ee703f07e426a64a50728c09575efb71e9a; anchor=class DeviceSettingsSession]`. - Target: `mobile/lib/led_backend_control.dart:9 [UTF8-LF sha256=4769c24f714e241c5acb41987f5cbefef35681a86fbcda40c92ffb7db934c33a; anchor=class LedBackendControl]`. - Target: `mobile/lib/led_backend.dart:5 [UTF8-LF sha256=ccea33fd885d514027e622061bf55daf4d0c3564f977529b9956c6df42d57491; anchor=class LedBackendState]`. -- Target: `web/index.html:2624 [UTF8-LF sha256=50951b137bc42eccc73d953ecf599c2d28d31ce2c041c0539b96d5ad3c747686; anchor=function renderLedBackendControl(anchor){]`. -- Target: `web/index.html:2595 [UTF8-LF sha256=50951b137bc42eccc73d953ecf599c2d28d31ce2c041c0539b96d5ad3c747686; anchor=function waitForLedBackend(]`. +- Target: `web/index.html:2641 [UTF8-LF sha256=aa518a96eea2dd7d787cb0a31d5191c78886e2e31605eda64458a0cea728835d; anchor=function renderLedBackendControl(anchor){]`. +- Target: `web/index.html:2612 [UTF8-LF sha256=aa518a96eea2dd7d787cb0a31d5191c78886e2e31605eda64458a0cea728835d; anchor=function waitForLedBackend(]`. - Retained: Actual contract-driven sections/selected-section navigation, grouped labeled typed controls, contextual options, retained draft on section changes, descriptions, load/save status and reload adapted to Flutter DeviceSettingsPage using the existing shared Pakar catalog. Tablet uses a searchable navigation rail; phone uses wrapping section chips. Actual Phosphor repertoire supplies verified icon codepoints. - Retained: Actual valueAtPath/updatePaths structured settings ownership adapted to separate public drafts and secret actions. DeviceSettingsSession uses the fully read canonical Pakar native/Web validation, observe/conflict and positive acknowledgment/exact public readback workflow rather than generic optimistic UI success. In-memory secrets never enter saved client preferences; one POST body per explicit operation, no mutation replay. - Retained: Runtime LED transmitter checkpoint reread all563 donor lines and verified SHA30a63cc1. Adapt actual contract-derived select options, field-scoped saving state and external-observation refresh to Flutter LedBackendControl/LedBackendState and the single canonical Web selector. Only the intersection of advertised compiled choices is offered; selection reflects actual driver telemetry and renderer mode stays independent. Replace updatePaths optimistic save with one correlated mutation and same-peer requested/active/readiness/error/persistence observation. WebSocket events settle the result; configured bounded HTTP fallback reads never replay the mutation. This is a scoped mechanism adaptation, not a direct TSX component import or full PreferencesTab parity. @@ -4197,7 +4198,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O - Target: `assets/web/localization.js:19 [UTF8-LF sha256=fc7a39cae41e490fba858a8c7129abf0a7064811c486ddf9ba1b115b79e7c0fb; anchor=function uiTr(text,values)]`. - Target: `tools/generate-font-assets.mjs:62 [UTF8-LF sha256=fdf6b75dac5afebad8598abbe408cd44bbf09cb306d4db91ee515add5ebb1412; anchor=const dictionary={}]`. -- Target: `firmware/esp/src/WebUi.h:795 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=// BEGIN SHARED LOCALIZATION]`. +- Target: `firmware/esp/src/WebUi.h:795 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=// BEGIN SHARED LOCALIZATION]`. - Retained: Fully reread all 630 current donor lines through EOF. Actual fa-dictionary fallback semantics remain reused for application copy, rather than translating arbitrary runtime data. Applicable native dictionary subset generates into the canonical Web module and actual firmware HTML; the new generic hardware/status/font/control vocabulary is useful pending consumer work, not an automatic dictionary import. - Retained: Added system/explicit language and Auto/LTR/RTL preferences, owned-template text/placeholder/accessibility snapshots, per-browser low-write persistence, shared font route and immutable peer-name boundary. - Retained: Persian Web regression slice: controller captions now include preferences, network/cloud/access/firmware and cell dialogs; capability mode labels participate in dictionary generation. Live telemetry and dynamic accessibility labels refresh in the selected language, real addresses release stale caption ownership, option values remain protocol-stable, and Persian text omits Latin letter spacing. Read-only actual HTML browser inspection verified mobile-width preferences/settings and reversible persistent locale switching; this is not live board acceptance. @@ -4242,7 +4243,7 @@ Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. O Verdict: **parity-gap**. Revision: `5a6961ce6a477a4726b7baf8a84d12fde1cdf6ad`. Original-byte SHA-256: `d6ee8217c05e96be2e20f9a40ab4c46249d57f58871c661a31c33e2310a92f0e`. - Target: `tools/generate-branding.mjs:18 [UTF8-LF sha256=816544b2525d3c9210a586b8c2c5d59ed6c51fab8ca4bda27fbf2edbdd451367; anchor='FAVICON':]`. -- Target: `firmware/esp/src/WebUi.h:142 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=]`. +- Target: `firmware/esp/src/WebUi.h:142 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=]`. - Target: `docs/BRANDING-PARITY.md:60 [UTF8-LF sha256=0bfa8122dc9d6034551304f2fed472ddebcff170e14a23f63011177aab75d2d3; anchor=## Explicit unfinished useful code and reasons]`. - Retained: Same resolved artwork binds favicon/touch/header before login; ESP embeds data instead of requesting a protected host filesystem icon. - Retained: Current 383-line donor was completely reread. Existing favicon/header/touch artwork mapping remains valid; this is not browser-platform parity. @@ -4901,7 +4902,7 @@ Verdict: **scoped-improvement**. Revision: `431104072952f694a35b3a83c19f13fbb098 - Target: `firmware/esp/src/WebAccess.h:31 [UTF8-LF sha256=774b524f4cd81c003e4139d0bb6cf3353d987674bbfb49d7a1b989ee2a232294; anchor=class WebAccess]`. - Target: `firmware/esp/src/AccessConfig.cpp:67 [UTF8-LF sha256=aba76ed621e1e107ecea9a44ab32cb077fa7d08c0422b3631b3afeadc4e8d198; anchor=bool AccessConfig::configure(]`. - Target: `desktop/src/ui/connection_controls.rs:213 [UTF8-LF sha256=02bbb46d280c606868f0f18220cb092c0dca2e07f9b06aa31bee1e4f4625ec65; anchor=if authentication == Some(true)]`. -- Target: `firmware/esp/src/WebUi.h:3635 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function presentDeviceAccess(info)]`. +- Target: `firmware/esp/src/WebUi.h:3652 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function presentDeviceAccess(info)]`. - Retained: Complete exact donor source read and live SHA-256 matched the inventoried revision. Retained middleware authorization, public login, credential validation and cookie/session admission concepts in the actual shared WebAccess implementation. Added saved explicit authentication opt-in, default-off Web/native behavior, verified atomic storage migration, bounded session/WS ownership, rate limiting, origin and peer/boot fencing. - Omitted/replaced code: `complexAuth hardcoded user/password; doLogin password/token response and diagnostic dump; /pass PU access-level commands`. Disposition: **replaced**. Reason: Factory authentication is not an opt-in. Password/token dumps disclose secrets, and the PU access-level business commands do not describe this LED board. Use explicit saved access settings and non-disclosing session routes instead. - Omitted/replaced code: `Duplicated run implementation, placeholder AuthenticationHandler/getAuthToken/session access-level skeleton and role=staff sample`. Disposition: **replaced**. Reason: The donor skeleton has unresolved identifiers and no complete role-based authorization contract. Imported the applicable route/session behavior into compiling middleware rather than enabling an incomplete authorization example. No implemented Pakar role support is claimed. @@ -4918,7 +4919,7 @@ Verdict: **scoped-improvement**. Revision: `431104072952f694a35b3a83c19f13fbb098 - Target: `firmware/esp/src/WebAccess.h:31 [UTF8-LF sha256=774b524f4cd81c003e4139d0bb6cf3353d987674bbfb49d7a1b989ee2a232294; anchor=class WebAccess]`. - Target: `firmware/esp/src/AccessConfig.cpp:67 [UTF8-LF sha256=aba76ed621e1e107ecea9a44ab32cb077fa7d08c0422b3631b3afeadc4e8d198; anchor=bool AccessConfig::configure(]`. - Target: `desktop/src/ui/connection_controls.rs:213 [UTF8-LF sha256=02bbb46d280c606868f0f18220cb092c0dca2e07f9b06aa31bee1e4f4625ec65; anchor=if authentication == Some(true)]`. -- Target: `firmware/esp/src/WebUi.h:3635 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=function presentDeviceAccess(info)]`. +- Target: `firmware/esp/src/WebUi.h:3652 [UTF8-LF sha256=dcd9e175d488ecbcb4c824fa7c7fd2004c5da9411c67851831940a4ba8881a73; anchor=function presentDeviceAccess(info)]`. - Retained: Complete exact donor source read and live SHA-256 matched the inventoried revision. Retained middleware authorization, public login, credential validation and cookie/session admission concepts in the actual shared WebAccess implementation. Added saved explicit authentication opt-in, default-off Web/native behavior, verified atomic storage migration, bounded session/WS ownership, rate limiting, origin and peer/boot fencing. - Omitted/replaced code: `complexAuth hardcoded user/password; doLogin password/token response and diagnostic dump; /pass PU access-level commands`. Disposition: **replaced**. Reason: Factory authentication is not an opt-in. Password/token dumps disclose secrets, and the PU access-level business commands do not describe this LED board. Use explicit saved access settings and non-disclosing session routes instead. - Omitted/replaced code: `Duplicated run implementation, placeholder AuthenticationHandler/getAuthToken/session access-level skeleton and role=staff sample`. Disposition: **replaced**. Reason: The donor skeleton has unresolved identifiers and no complete role-based authorization contract. Imported the applicable route/session behavior into compiling middleware rather than enabling an incomplete authorization example. No implemented Pakar role support is claimed. @@ -6651,7 +6652,7 @@ Verdict: **equivalent-behavior**. Revision: `filesystem-snapshot-no-git`. Origin - Target: `assets/themes/browser-appearance.js:70 [UTF8-LF sha256=056ef41691b92dacbcd7c75b11ff38a2e492093e769aab26dc2577785994de54; anchor=function applyPrepaintLocale()]`. - Target: `tools/generate-web-appearance.mjs:35 [UTF8-LF sha256=e57a615bf5134b718d6df7b644e56faced0c0ef73e8662cf8cb06c05e23e59b4; anchor=replaceBlock('// BEGIN BROWSER CONTROLLER']`. -- Target: `firmware/esp/src/WebUi.h:9 [UTF8-LF sha256=37f97386ad9cc8d87df469629066e20e0601adcee6641b52af9687bc807eca95; anchor=