···11-# Phase 2.5 #1 Agent Report — Core Background Renderer to v2 Tile Mechanics
11+# Phase 2.5 #3 Agent Report — createExtensionWindow migration audit
2233-## What landed
33+## Triage stub (in progress)
4455-Single jj commit: `feat(core-glue + app/background): migrate core background renderer to v2 tile-preload + trustedBuiltin`
66-77-(Files edited in this commit; the `core-glue.ts` skeleton already existed in HEAD from a prior agent but was not wired up — this commit makes it live by editing `main.ts` / `entry.ts` and the renderer-side HTML/JS + tile-preload API additions.)
88-99-### Files changed
55+Target: migrate `createExtensionWindow()` in `backend/electron/main.ts` from
66+v1 `preload.js` to v2 tile-preload, OR document why it stays.
1071111-- `backend/electron/main.ts` — `createBackgroundWindow()` refactored to delegate to `initCore()` from `./core-glue.js`. `getBackgroundWindow()` now prefers `getCoreBackgroundWindow()`. `tilePreloadPath` resolved + cached in `initialize()` (was duplicated inside `loadExtensions()`). ~150 lines of dead `setWindowOpenHandler` child-window logic removed (native `window.open()` never happens from core background HTML — only `api.window.open()` is used, which routes through `tile:window:open`). Unused imports dropped (`trackWindowLoad`, `updateItemTitle`, `updateItemFavicon`, `updateModeForNavigation`, `getPreloadPath`, `APP_DEF_WIDTH`, `APP_DEF_HEIGHT`, `trackWindow`, `addEscHandler`, `winDevtoolsConfig`, `closeOrHideWindow`, `getPrefs`).
1212-- `backend/electron/entry.ts` — `createBackgroundWindow()` call is now `await`ed (it returns a Promise).
1313-- `backend/electron/tile-preload.cts` — added `api.quit` / `api.restart` / `api.chromeExtensions.*` (all trustedBuiltin-gated) and extended `api.theme` with `get/list/getAll/setTheme/setColorScheme/setWindowColorScheme` when `trustedBuiltin === true`. The strict `tile:theme:*` surface is unchanged for feature tiles.
1414-- `app/background.html` — CSP updated to `script-src 'self' 'unsafe-inline'` (inline `<script type=module>` now required by the shim below). Replaced the old `<script src="./index.js">` with a short inline module that: (a) `await api.initialize()`, (b) `await import('./index.js')` then `await mod.init()`, (c) sets `window.__coreReady = true`. Same shape as `app/_test/index.html`.
1515-- `app/index.js` — `init` is now `export const init = async () => {...}` and the old `window.addEventListener('load', ...)` bootstrap is removed. Core startup is explicitly driven by `background.html` so subscribers are registered before any downstream publisher fires.
1616-- `backend/electron/core-glue.ts` — already present in HEAD; no further edits needed.
1717-1818-## Validation results (all via `yarn test:grep`, `yarn test:unit`)
1919-2020-| Test | Result |
2121-|------|--------|
2222-| `v2 trustedBuiltin tile → v2 trustedBuiltin tile pubsub round-trip` | 1/1 pass |
2323-| `direct pubsub kagi execution works` | 1/1 pass |
2424-| `tag command with # prefixed tags...` | 1/1 pass |
2525-| `open and close settings` | 1/1 pass |
2626-| `Group Mode Context` | 5/5 pass |
2727-| `HUD` | 11/11 pass |
2828-| `yarn test:unit` | 565/565 pass, 0 failures |
2929-3030-Window-list inspection from the `v2 trustedBuiltin tile` test confirms `peek://app/background.html` now appears in the v2 tile window list alongside cmd/hud/page/test:
3131-3232-```
3333-peek://app/background.html, peek://cmd/index.html, peek://hud/index.html,
3434-peek://page/background.html, peek://test/index.html, ... (29 feature tiles)
3535-```
3636-3737-## Surprises / dependencies discovered in `app/index.js`
3838-3939-- `api.theme` had to be augmented under trustedBuiltin. The strict `api.theme` only has `getInfo`/`onChange`. The core palette commands (`theme light`, `theme dark`, `theme next`, `theme light here`, etc.) need `get`/`list`/`setTheme`/`setColorScheme`/`setWindowColorScheme`. Added as trustedBuiltin-gated thin wrappers over the existing `theme:*` `ipcMain.handle` channels.
4040-- `api.quit` / `api.restart` don't have an `ipcMain.handle` path — they use `ipcMain.on` (fire-and-forget). `api.invoke` can't substitute, so added dedicated `.send`-based wrappers under trustedBuiltin.
4141-- `api.chromeExtensions.getUiEntries()` / `.openPage()` are used by `registerExtensionCommands()` to register one cmd-palette entry per chrome extension popup/options page. Added trustedBuiltin-gated wrappers.
4242-- `api.debug` / `api.debugLevel` / `api.debugLevels` — not present in tile-preload. `app/log.js` reads them defensively (`api?.debug || false`), so the renderer falls through to no-debug-logging. Acceptable for now; if we want debug logs back, add them to tile-preload's "always available" surface.
4343-- The big `setWindowOpenHandler` block in the old `createBackgroundWindow` was 150+ lines handling `window.open()` from the background renderer. After v2 migration, `api.window.open` routes via `tile:window:open` (which in turn delegates to the canonical `window-open` IPC handler in `ipc.ts`), so **nothing inside `app/index.js` or its imports triggers native `window.open()`**. Confirmed by grep + runtime log — the block was dead under v1 too, kept only because the code path worked.
4444-- `app/background.html` needed `'unsafe-inline'` in its CSP — pure ES-module inline scripts (`type="module"`) are still `inline` from CSP's perspective. Every other core renderer (`_test`, `cmd`, `hud`, `page`) already has this; background.html was the holdout.
4545-- `createBackgroundWindow` is now async. The only caller (`entry.ts:780`) was synchronous fire-and-forget; converted to `await`. If any Tauri port was going to reuse the electron entry shape, it needs the same change.
4646-4747-## Items for Phase 2.5 #2 / #3
4848-4949-- **`entry.ts:179` webview preload injection** still uses v1 `preload.js`. Unchanged.
5050-- **`main.ts::createExtensionWindow()`** (line ~1100) still creates external-extension windows with v1 `preload.js`. Unchanged.
5151-- **`registerWindow` call** previously inside the old `createBackgroundWindow` body now happens INSIDE the new `createBackgroundWindow` wrapper — so `closeOrHideWindow` / `countVisibleWindows` / session-restore skip logic continues to work via the `address === WEB_CORE_ADDRESS` check.
5252-- **`core-glue.ts`** registers the background window via `registerTrustedBuiltinWindow()` for pubsub broadcast; the `registerWindow()` call in session-registry terms is done in the main.ts wrapper. The two are orthogonal — pubsub broadcast vs session-registry key-lookup.
5353-- **v1 `preload.js` not yet removed.** Still consumed by webview injection (`entry.ts:179`), `createExtensionWindow` (main.ts), window-open IPC fallback in `ipc.ts`, and Tauri's `include_str!`. Phase 3 / 4.
5454-- **Minor:** `app/_test/index.html` and `app/background.html` now have nearly identical bootstrap shims — could factor into a shared `app/shared/trusted-builtin-bootstrap.js` in a later cleanup. Not blocking.
5555-5656-## Window list inspection
5757-5858-From the `v2-pubsub-reproducer.spec.ts` run above, the list of live windows at steady state now contains `peek://app/background.html` as expected:
5959-6060-```
6161-peek://app/background.html, peek://app/extension-host.html,
6262-peek://app/settings/settings.html, peek://cmd/index.html,
6363-peek://hud/index.html, peek://page/background.html,
6464-peek://test/index.html, ...
6565-```
6666-6767-`peek://app/extension-host.html` is still there — phase 2.5 #4 audit concluded it's retained solely for legacy smoke-test assertions, not for actual extension loading.
88+Initial scan complete. Full audit next — see later sections.