← Commit history
Record the hard-won never-force-foreground rule (focus theft makes the user's keystrokes leak into your controls + corrupts the flow); clipboard-assist is the non-rude picker fill
3 files changed
+59−13
docs/INSTALL-FLOW.md+11@@ -111,6 +111,17 @@ loaded: own and keep hardening; the folder-picker step is the fragile part we iterate on. - **Manual load-unpacked.** The user does it themselves (the *Fork and develop* guide shows it). +> ⛔ **The install drives the user's screen in the BACKGROUND - never force the browser to the+> foreground.** Stealing focus (`desktop_bring_to_front`, or any SendInput verb that foregrounds first)+> is rude AND corrupts the install: if the user keeps typing, their keystrokes land in the control you+> just focused (e.g. the extensions search box), silently changing your filter and hiding the card you+> were acting on. We learned this live - a foregrounded search became `Adoms` and the extension+> "vanished." The orchestration uses background UIA (`desktop_ui_click` / `desktop_ui_set` /+> `desktop_navigate` / `desktop_screenshot_window`) throughout; the one keyboard-only step (typing the+> path into the folder picker) is done via **clipboard-assist** (we put the path on the clipboard and+> the user pastes) rather than by stealing focus to type. Foreground is a narrated, last-resort+> exception, never the default.+ Chrome and Edge are independent: load it in whichever the user wants, or both. The host is registered per browser (step 3), so each browser the extension runs in connects its own host.
skills/installing-the-extension/SKILL.md+39−13@@ -50,6 +50,27 @@ what you're doing ("Adom: turning on Developer mode", "Adom: selecting the exten especially **what THEY must do** ("Click Select Folder to finish", "Paste the path with Ctrl+V"). Clear it when done. Treat the install as a guided, narrated process, never a silent one. +## ⛔⛔ NEVER force the browser to the foreground (rude AND it corrupts your own work)+Foregrounding the user's browser - `desktop_bring_to_front`, OR any SendInput verb (`desktop_type`,+`desktop_press_key`, `desktop_click`) which foreground the target first - is **disruptive and actively+dangerous while the user is working**. It steals focus, so **the user's very next keystroke lands in+whatever control YOU just focused** - e.g. the extensions **Search box** - which silently changes your+filter and **hides the card you were acting on**. Learned the hard way: while foregrounded, the user kept+typing and the search became `Adoms` / `Adom for Chromeing`, so the Adom card vanished and the flow+derailed. It is also just rude - they are mid-task on their own machine.++Rules, in order:+- **Drive entirely with BACKGROUND verbs** - `desktop_ui_click` (UIA Invoke), `desktop_ui_set` (SetValue),+ `desktop_navigate`, `desktop_screenshot_window`. **None steal focus**, so the user keeps typing safely+ and your control state can't be corrupted by their keystrokes. This covers almost the entire flow.+- The only steps that might tempt a foreground are the **folder-picker path-fill** and the+ **Remove-confirm bubble**. Do NOT reach for `bring_to_front`/SendInput by default - use the background+ or clipboard paths (below) first.+- **If a step truly cannot be done in the background**, treat foreground as a last resort: `desktop_caption`+ the user to pause typing for a moment, do the single action, and return immediately. Never hold the+ foreground, never do it silently, and never do it while the user is actively typing if there is any+ other way.+ ## The flow (background; never foreground the user's work) Open a fresh background window you own, get its `hwnd`, and drive **that** (never the user's tabs): ```@@ -80,23 +101,28 @@ desktop_ui_click {hwnd:<W>, automationId:"loadUnpacked"} # VERIFIED sta ``` The picker is a Win32 dialog (`#32770`, title "Select the extension directory."). ⚠️ **It opens in an arbitrary last-used directory (observed: Downloads) - NEVER trust "it remembers the folder."** You MUST-set the path. Fill it by this ladder (most reliable first; all AD verbs, all observed live):+set the path. ⛔ The whole catch: filling this field needs keyboard input, and SendInput+(`desktop_type`/`desktop_press_key`) **foregrounds the window** - the rude, work-corrupting move above.+So prefer the path that keeps the user in control: -1. **Address bar - VERIFIED to work.** Focus the picker, then:+1. **Clipboard assist - PREFERRED when the user is at the machine (you never steal focus).** Put the+ absolute path on the clipboard, `desktop_caption {text:"Adom: paste this path (Ctrl+V) into the Folder+ box, then click Select Folder"}`, and let the USER do the single paste + click. You stay background;+ they finish the one keyboard step. Confirm by screenshot that the card loaded.+2. **Address bar via SendInput - VERIFIED to work, but it FOREGROUNDS (last resort; user away/consenting).**+ First `desktop_caption {text:"Adom: one moment, please don't type"}`, then: ```- desktop_press_key {hwnd:<picker>, keys:"ctrl+l"} # focus the address bar+ desktop_press_key {hwnd:<picker>, keys:"ctrl+l"} # focus the picker address bar (FOREGROUNDS) desktop_type {hwnd:<picker>, text:"<abs path to extension>"}- desktop_press_key {hwnd:<picker>, keys:"enter"} # navigates INTO the folder (breadcrumb + file list confirm it)- desktop_ui_click {hwnd:<picker>, automationId:"1"} # the "Select Folder" button (id "1", invokable) -> commits+ desktop_press_key {hwnd:<picker>, keys:"enter"} # navigates INTO the folder (breadcrumb confirms it)+ desktop_ui_click {hwnd:<picker>, automationId:"1"} # "Select Folder" (id "1", invokable) -> commits ```- SendInput-based, so the picker must be foreground - it is (modal). Keep it brief.-2. **Clipboard assist (put the USER in the loop for the one fragile step).** Copy the absolute path to- the clipboard, `desktop_caption {text:"Paste this path (Ctrl+V) into the Folder box, then Select Folder"}`,- and let them finish. Good when automation is uncertain or you want consent at the commit.-3. **UIA SetValue does NOT work here (verified).** The Folder combobox has **no ValuePattern** (`desktop_ui_set`- returns "control found but has NO ValuePattern"). Do not rely on `ui_set` for the picker path.-4. **Coordinate click + type (last resort, most fragile).** `desktop_click` the Folder box by its rect,- then `desktop_type`. Layout-dependent; only if 1 fails.+ Do this ONLY when the user isn't typing; keep it to this one quick burst, then leave focus alone.+3. **UIA SetValue does NOT work here (verified).** The Folder combobox has **no ValuePattern**+ (`desktop_ui_set` -> "control found but has NO ValuePattern"). There is no clean background fill for+ this field - which is exactly why clipboard-assist (1) beats foregrounding.+4. **Coordinate click + type (most fragile + foregrounds).** `desktop_click` the Folder box by its rect,+ then `desktop_type`. Layout-dependent; avoid. **ALWAYS screenshot and READ the path BEFORE committing.** `desktop_screenshot_window {hwnd:<W>}` (the BROWSER hwnd) returns the picker in its `screenshots[]` array - confirm the breadcrumb/Folder shows
skills/native-browser-safety/SKILL.md+9@@ -36,6 +36,15 @@ drive a window without foregrounding it: `nbrowser_screenshot` (CDP) and `deskto reason to pull a window forward. Foregrounding is the **user's** choice (`desktop_bring_to_front`), made by them, only when they want to watch. +This is not just etiquette - **foregrounding corrupts your own work.** When you steal focus while the+user is typing, **their next keystrokes land in whatever control you just focused** (a search box, a+text field), silently changing your state and derailing the task (real case: a foregrounded+`chrome://extensions` search turned into `Adoms` mid-flow and the target extension vanished). Note this+applies to **SendInput verbs too** - `desktop_type` / `desktop_press_key` / `desktop_click` foreground+the target before sending. Prefer background UIA (`desktop_ui_click` Invoke, `desktop_ui_set` SetValue)+and `desktop_navigate`; if a step genuinely needs foreground keyboard input, caption the user to pause,+do the one action, and return focus immediately.+ ## The "debugging this browser" bar is expected, not a bug CDP verbs (`click`, `type`, `screenshot`, `eval`, ...) attach `chrome.debugger`, which makes Chrome show the yellow `"Adom for Chrome & Edge" started debugging this browser` bar. The bridge