From facd53ed5fc932c53aa7c3a5f4100da234906f9a Mon Sep 17 00:00:00 2001 From: Hermes SysOp Date: Thu, 12 Nov 2026 17:40:27 +0100 Subject: fix(newos4): ?ui= is an opt-in too — the gate had killed every shared mode link (v4.6.163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4.6.162 shipped the opt-in gate as `get('ui') === '1'`. But the UI shell has always treated `?ui=` as a REQUEST — `module-uishell.js` reads `q = get('ui')` and honours it when the value is one of `lazyIds()` (easy|chat|studio|workspace|commander|cockpit), with `_fromQuery` set so the request never becomes a stored preference. So every shared link of the form `main.html?ui=chat` stopped mounting the shell entirely and booted classic, silently, with no error: the gate required a literal '1' that the shell's own convention never sends. Found by an independent verification pass that tried `probe-ui-modes.py --cycle` against prod and got `FAIL easy@390x844: wait_for_selector timeout` — a false red on a working build, which traced back to this. The probe's own breakage was mine (I had just changed its default base to `?ui=1`, and it appends `?ui=`, producing `?ui=1?ui=easy`); that is fixed in the next commit. Gate now: opt in on ANY `ui` value except an explicit off ('0'/'false'), plus the localStorage key. q = get('ui'); if (q !== null && q !== '' && q !== '0' && q !== 'false') return true; return localStorage.getItem('webx11_ui_experimental') === '1'; Verified on the served page (v4.6.163): * `?ui=chat` -> uiShell object, data-ui-mode=chat, body wx11-ui-chat, #chat-stream present, _fromQuery=true, picker NOT shown, and localStorage UNCHANGED (webx11_ui_experimental=null, webx11_ui_mode=null) — a link is not a preference. * no flag -> uiShell undefined, 0 #ui-root, no picker (unchanged from v4.6.162). * `?ui=1` -> shell + picker (guard's browser assertion still passes). Served core-bundle.js byte-identical to disk; guard green (7/7 checks, rc=0); probe-ui-modes.py --cycle ALL PASS 13 checks; maintain.py --fix PASS. --- modules/core/core-bundle.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'modules/core/core-bundle.js') diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index d52764d..349c02b 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -4104,7 +4104,13 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm // (cron ui-gate-guard) fails if the gate is lost or the bare call returns. const _uiExp = (function () { try { - if (new URLSearchParams(location.search).get('ui') === '1') return true; + // ANY `?ui=` opts in except an explicit off ('0'/'false'), because + // `?ui=` is the shell's own shared-link request (?ui=chat deep-links a + // mode, validated against lazyIds inside the shell). Requiring exactly '1' + // made every shared mode link boot classic with no error — measured + // 2026-11-12, the day this gate shipped. + const q = new URLSearchParams(location.search).get('ui'); + if (q !== null && q !== '' && q !== '0' && q !== 'false') return true; return localStorage.getItem('webx11_ui_experimental') === '1'; } catch (e) { return false; } })(); -- cgit v1.2.3