@omega.js/desktop 0.51.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +18 -13
  2. package/dist/assets/css/core/_initialize.scss +1 -1
  3. package/dist/assets/js/core/app-shell.js +14 -15
  4. package/dist/assets/themes/_template/_theme.js +6 -6
  5. package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
  6. package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
  7. package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
  8. package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
  9. package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
  10. package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
  11. package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
  12. package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
  13. package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
  14. package/dist/assets/themes/base/_theme.js +4 -3
  15. package/dist/assets/themes/bootstrap/_theme.js +2 -2
  16. package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
  17. package/dist/assets/themes/classy/_theme.js +8 -6
  18. package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
  19. package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
  20. package/dist/assets/themes/neobrutalism/_theme.js +5 -5
  21. package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
  22. package/dist/assets/themes/newsflash/_theme.js +6 -6
  23. package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
  24. package/dist/build.js +87 -111
  25. package/dist/cli.js +1 -1
  26. package/dist/commands/build.js +2 -2
  27. package/dist/commands/cdp/capture.js +2 -2
  28. package/dist/commands/cdp/quit.js +2 -2
  29. package/dist/commands/cdp/relaunch.js +2 -2
  30. package/dist/commands/cdp/theme.js +1 -1
  31. package/dist/commands/clean.js +2 -2
  32. package/dist/commands/deploy.js +4 -4
  33. package/dist/commands/finalize-release.js +4 -4
  34. package/dist/commands/install.js +3 -3
  35. package/dist/commands/launch.js +2 -2
  36. package/dist/commands/lib/deploy-precheck.js +3 -3
  37. package/dist/commands/lib/ensure-target.js +6 -6
  38. package/dist/commands/package.js +2 -2
  39. package/dist/commands/publish.js +2 -2
  40. package/dist/commands/release.js +3 -3
  41. package/dist/commands/runner.js +145 -48
  42. package/dist/commands/sign-windows.js +5 -5
  43. package/dist/commands/test.js +4 -4
  44. package/dist/commands/update.js +2 -2
  45. package/dist/commands/validate-certs.js +4 -4
  46. package/dist/commands/version.js +3 -3
  47. package/dist/defaults/.github/workflows/build.yml +2 -0
  48. package/dist/defaults/AGENTS.md +17 -8
  49. package/dist/defaults/config/omega.json5 +7 -7
  50. package/dist/defaults/hooks/build/post.js +1 -1
  51. package/dist/defaults/hooks/build/pre.js +1 -1
  52. package/dist/defaults/hooks/deploy/pre.js +1 -1
  53. package/dist/defaults/hooks/release/post.js +1 -1
  54. package/dist/defaults/hooks/release/pre.js +1 -1
  55. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  56. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  57. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  58. package/dist/defaults/src/integrations/context-menu/index.js +2 -2
  59. package/dist/defaults/src/integrations/menu/index.js +3 -3
  60. package/dist/defaults/src/integrations/tray/index.js +3 -3
  61. package/dist/defaults/src/main.js +3 -5
  62. package/dist/defaults/src/preload.js +3 -5
  63. package/dist/defaults/test/README.md +2 -2
  64. package/dist/gulp/main.js +9 -10
  65. package/dist/gulp/tasks/audit.js +7 -7
  66. package/dist/gulp/tasks/build-config.js +8 -8
  67. package/dist/gulp/tasks/bundle.js +16 -16
  68. package/dist/gulp/tasks/defaults.js +3 -3
  69. package/dist/gulp/tasks/distribute.js +2 -2
  70. package/dist/gulp/tasks/html.js +9 -9
  71. package/dist/gulp/tasks/package-quick.js +3 -3
  72. package/dist/gulp/tasks/package.js +3 -3
  73. package/dist/gulp/tasks/release.js +3 -3
  74. package/dist/gulp/tasks/sass.js +6 -6
  75. package/dist/gulp/tasks/serve.js +4 -4
  76. package/dist/hooks/notarize-artifacts.js +1 -1
  77. package/dist/hooks/notarize.js +1 -1
  78. package/dist/index.js +5 -8
  79. package/dist/lib/_environment-mixin.js +50 -0
  80. package/dist/lib/_lifecycle-mixin.js +45 -0
  81. package/dist/lib/analytics.js +33 -35
  82. package/dist/lib/app-state.js +14 -14
  83. package/dist/lib/auth-flow.js +18 -18
  84. package/dist/lib/auth-persistence.js +12 -12
  85. package/dist/lib/auth.js +421 -0
  86. package/dist/lib/auto-updater.js +49 -49
  87. package/dist/lib/context-menu.js +13 -13
  88. package/dist/lib/context.js +19 -19
  89. package/dist/lib/deep-link.js +34 -34
  90. package/dist/lib/fontawesome.js +5 -5
  91. package/dist/lib/ipc.js +4 -4
  92. package/dist/lib/menu.js +25 -25
  93. package/dist/lib/protocol.js +5 -5
  94. package/dist/lib/remote-config.js +22 -22
  95. package/dist/lib/remote-scripts.js +21 -21
  96. package/dist/lib/restart-manager/index.js +28 -28
  97. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  98. package/dist/lib/sign-helpers/sign-events.js +1 -1
  99. package/dist/lib/startup.js +18 -13
  100. package/dist/lib/storage.js +10 -10
  101. package/dist/lib/templating.js +16 -16
  102. package/dist/lib/theme.js +10 -10
  103. package/dist/lib/tray.js +27 -27
  104. package/dist/lib/usage.js +11 -11
  105. package/dist/lib/window-manager.js +26 -26
  106. package/dist/main.js +398 -483
  107. package/dist/preload.js +236 -176
  108. package/dist/renderer.js +417 -391
  109. package/dist/runner/job-started.js +1 -1
  110. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  111. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  112. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  113. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  114. package/dist/test/harness/boot-entry.js +22 -20
  115. package/dist/test/harness/main-entry.js +31 -30
  116. package/dist/test/harness/renderer-entry.js +5 -5
  117. package/dist/test/harness/renderer-preload.js +137 -141
  118. package/dist/test/index.js +10 -10
  119. package/dist/test/runner.js +2 -2
  120. package/dist/test/runners/boot.js +7 -6
  121. package/dist/test/runners/electron.js +3 -2
  122. package/dist/test/runners/render-event.js +2 -2
  123. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  124. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  125. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  126. package/dist/test/suites/boot/theme.test.js +13 -13
  127. package/dist/test/suites/build/audit.test.js +1 -1
  128. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  129. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  130. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  131. package/dist/test/suites/build/brand-scss.test.js +1 -1
  132. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  133. package/dist/test/suites/build/cli.test.js +2 -2
  134. package/dist/test/suites/build/config-schema.test.js +5 -5
  135. package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
  136. package/dist/test/suites/build/deploy-hook.test.js +3 -3
  137. package/dist/test/suites/build/ensure-target.test.js +2 -2
  138. package/dist/test/suites/build/env-delivery.test.js +2 -2
  139. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  140. package/dist/test/suites/build/exports.test.js +9 -8
  141. package/dist/test/suites/build/get-config.test.js +4 -4
  142. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  143. package/dist/test/suites/build/merge-line-files.test.js +1 -1
  144. package/dist/test/suites/build/omega-shell.test.js +34 -2
  145. package/dist/test/suites/build/omega.test.js +350 -0
  146. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  147. package/dist/test/suites/build/runner.test.js +612 -5
  148. package/dist/test/suites/build/sentry.test.js +2 -2
  149. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  150. package/dist/test/suites/build/templating.test.js +3 -3
  151. package/dist/test/suites/build/test-stealth.test.js +7 -9
  152. package/dist/test/suites/build/url-helpers.test.js +55 -56
  153. package/dist/test/suites/build/validate-config.test.js +2 -2
  154. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  155. package/dist/test/suites/main/analytics.test.js +59 -59
  156. package/dist/test/suites/main/app-state.test.js +66 -66
  157. package/dist/test/suites/main/auth-flow.test.js +41 -41
  158. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  159. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  160. package/dist/test/suites/main/auth.test.js +336 -0
  161. package/dist/test/suites/main/auto-updater.test.js +134 -134
  162. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  163. package/dist/test/suites/main/context-menu.test.js +51 -50
  164. package/dist/test/suites/main/context.test.js +25 -25
  165. package/dist/test/suites/main/deep-link.test.js +74 -74
  166. package/dist/test/suites/main/fontawesome.test.js +27 -27
  167. package/dist/test/suites/main/ipc.test.js +35 -35
  168. package/dist/test/suites/main/menu.test.js +101 -100
  169. package/dist/test/suites/main/protocol.test.js +19 -19
  170. package/dist/test/suites/main/remote-config.test.js +63 -63
  171. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  172. package/dist/test/suites/main/request.test.js +71 -0
  173. package/dist/test/suites/main/restart-manager.test.js +33 -33
  174. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  175. package/dist/test/suites/main/startup.test.js +26 -26
  176. package/dist/test/suites/main/stealth-window.test.js +1 -1
  177. package/dist/test/suites/main/storage.test.js +25 -25
  178. package/dist/test/suites/main/theme.test.js +34 -34
  179. package/dist/test/suites/main/tray.test.js +79 -79
  180. package/dist/test/suites/main/url-helpers.test.js +133 -133
  181. package/dist/test/suites/main/usage.test.js +25 -25
  182. package/dist/test/suites/main/window-bounds.test.js +27 -27
  183. package/dist/test/suites/main/window-manager.test.js +44 -44
  184. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  185. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  186. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  187. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  188. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
  189. package/dist/test/utils/extended-mode-warning.js +1 -1
  190. package/dist/utils/boot-harness.js +56 -0
  191. package/dist/utils/mode-helpers.js +2 -15
  192. package/dist/utils/ship-keys.js +3 -3
  193. package/dist/utils/signing-status.js +51 -0
  194. package/dist/utils/test-events.js +7 -0
  195. package/dist/utils/test-stealth.js +6 -6
  196. package/dist/utils/url-helpers.js +52 -42
  197. package/dist/utils/user-agent.js +44 -0
  198. package/dist/vendor/account/engine.js +3 -3
  199. package/dist/vendor/account/index.js +14 -45
  200. package/dist/vendor/account/resolve-account.js +44 -0
  201. package/dist/vendor/account/schema.js +1 -1
  202. package/dist/vendor/account/user.js +99 -0
  203. package/dist/vendor/config/client-config.js +1 -1
  204. package/dist/vendor/config/environment.js +11 -30
  205. package/dist/vendor/config/index.js +13 -12
  206. package/dist/vendor/config/load.js +1 -2
  207. package/dist/vendor/config/platforms.js +1 -1
  208. package/dist/vendor/config/repo.js +24 -0
  209. package/dist/vendor/config/retired-keys.js +2 -2
  210. package/dist/vendor/config/schema.js +5 -8
  211. package/dist/vendor/config/site-global.js +2 -3
  212. package/dist/vendor/config/validate.js +1 -2
  213. package/dist/vendor/config/winback.js +1 -1
  214. package/dist/vendor/devkit/actions-secrets.js +1 -1
  215. package/dist/vendor/devkit/attach-log-file.js +1 -1
  216. package/dist/vendor/devkit/brand-version.js +162 -1
  217. package/dist/vendor/devkit/build-json.js +1 -1
  218. package/dist/vendor/devkit/cli-router.js +3 -4
  219. package/dist/vendor/devkit/defaults-engine.js +9 -11
  220. package/dist/vendor/devkit/deploy.js +64 -4
  221. package/dist/vendor/devkit/git-remote.js +78 -1
  222. package/dist/vendor/devkit/local.js +53 -3
  223. package/dist/vendor/devkit/lockfile.js +127 -0
  224. package/dist/vendor/devkit/merge-line-files.js +2 -3
  225. package/dist/vendor/devkit/pack-local.js +4 -7
  226. package/dist/vendor/devkit/preludes/origin-heal.js +35 -49
  227. package/dist/vendor/devkit/target-secrets.js +34 -45
  228. package/dist/vendor/devkit/test/runner-core.js +6 -6
  229. package/dist/vendor/monitoring/env.js +2 -2
  230. package/dist/vendor/monitoring/index.js +1 -1
  231. package/dist/vendor/monitoring/main.js +1 -1
  232. package/dist/vendor/monitoring/preload.js +1 -1
  233. package/dist/vendor/monitoring/renderer.js +1 -1
  234. package/docs/analytics.md +8 -8
  235. package/docs/app-state.md +19 -19
  236. package/docs/audit.md +4 -4
  237. package/docs/{client-bridge.md → auth.md} +88 -73
  238. package/docs/auto-updater.md +8 -8
  239. package/docs/boot-sequence.md +11 -6
  240. package/docs/build-system.md +1 -1
  241. package/docs/cdp-debugging.md +1 -1
  242. package/docs/common-mistakes.md +7 -7
  243. package/docs/config-schema.md +1 -1
  244. package/docs/context-menu.md +13 -13
  245. package/docs/context.md +11 -11
  246. package/docs/css.md +3 -9
  247. package/docs/deep-link.md +25 -25
  248. package/docs/environment-detection.md +16 -16
  249. package/docs/fontawesome.md +7 -5
  250. package/docs/hooks.md +8 -8
  251. package/docs/index.md +39 -28
  252. package/docs/ipc.md +10 -10
  253. package/docs/lib-modules.md +9 -9
  254. package/docs/logging.md +12 -14
  255. package/docs/menu.md +18 -18
  256. package/docs/releasing.md +4 -2
  257. package/docs/remote-config.md +9 -9
  258. package/docs/remote-scripts.md +12 -12
  259. package/docs/restart-manager.md +8 -8
  260. package/docs/runner.md +12 -10
  261. package/docs/sentry.md +4 -4
  262. package/docs/shared/analytics.md +1 -1
  263. package/docs/shared/brands.md +1 -1
  264. package/docs/shared/breaking-changes.md +79 -13
  265. package/docs/shared/config.md +24 -21
  266. package/docs/shared/deploys.md +30 -7
  267. package/docs/shared/local-dev.md +5 -3
  268. package/docs/shared/logging.md +1 -1
  269. package/docs/shared/monitoring.md +5 -5
  270. package/docs/shared/testing.md +2 -2
  271. package/docs/shared/theming.md +1 -1
  272. package/docs/shared/translation.md +19 -10
  273. package/docs/signing.md +1 -1
  274. package/docs/startup.md +16 -16
  275. package/docs/storage.md +11 -11
  276. package/docs/templating.md +3 -3
  277. package/docs/test-boot-layer.md +12 -12
  278. package/docs/test-framework.md +17 -17
  279. package/docs/themes.md +7 -7
  280. package/docs/tooltips.md +2 -2
  281. package/docs/tray.md +31 -31
  282. package/docs/usage.md +7 -7
  283. package/docs/verts.md +1 -1
  284. package/docs/windows.md +22 -22
  285. package/package.json +3 -4
  286. package/dist/lib/client-bridge.js +0 -374
  287. package/dist/lib/logger.js +0 -4
  288. package/dist/test/suites/build/manager.test.js +0 -213
  289. package/dist/test/suites/main/client-bridge.test.js +0 -262
@@ -4,16 +4,16 @@ Built-in test framework for both @omega.js/desktop itself and consumer projects.
4
4
 
5
5
  ## 🚫 NEVER mock — test against the real harness (HARD RULE)
6
6
 
7
- **Do NOT hand-roll fake/stub/mock objects** — no `mockManager`, fake `ipc`/`storage`/`window`/`tray`, stubbed `app`/`BrowserWindow`, or fake IPC channels. Every test gets the **real** framework context:
7
+ **Do NOT hand-roll fake/stub/mock objects**: no mock `omega`, fake `ipc`/`storage`/`window`/`tray`, stubbed `app`/`BrowserWindow`, or fake IPC channels. Every test gets the **real** framework context:
8
8
 
9
9
  - `build` runs real @omega.js/desktop helper code in plain Node.
10
- - `main` / `renderer` / `boot` run inside a **real spawned Electron process**, where `ctx.manager` (and boot's `inspect({ manager })`) is the **real booted Manager** — real `manager.storage`, `manager.ipc`, `manager.tray`, `manager.windows`, etc. Use them; exercise the code the way production does.
10
+ - `main` / `renderer` / `boot` run inside a **real spawned Electron process**, where `ctx.omega` (and boot's `inspect({ omega })`) is the **real booted main-process instance**: real `omega.storage`, `omega.ipc`, `omega.tray`, `omega.windows`, etc. Use them; exercise the code the way production does.
11
11
 
12
12
  **Pure functions are the ONLY exception.** A function with zero I/O (config-defaults merge, icon-path resolver, schema validator, CLI alias resolver, a string/number transform) can be `require()`d and called directly with plain inputs — that's not mocking, there's nothing to mock. The moment a function touches `app.*` / `BrowserWindow` / `ipcMain` / `Tray` / the real bundle / an external service, it MUST run against the real harness in the appropriate layer (`main` / `renderer` / `boot`), not a stub.
13
13
 
14
14
  **Real external APIs are gated behind extended mode (`TEST_EXTENDED_MODE`), NOT mocked** (see [Extended vs normal mode](#extended-vs-normal-mode) below). Normal mode skips them *in the source*; extended mode runs them for real. The test never fakes them. **Anything an extended test creates in a real external system MUST be cleaned up** by the test (via the suite's `cleanup(ctx)` hook) — external systems are not reset between runs.
15
15
 
16
- If you find yourself writing `const mockX = {...}` to satisfy code under test, STOP — pass the real `ctx.manager` (or its real sub-object), or, if the function is genuinely pure, call it directly with plain data.
16
+ If you find yourself writing `const mockX = {...}` to satisfy code under test, STOP: pass the real `ctx.omega` (or its real sub-object), or, if the function is genuinely pure, call it directly with plain data.
17
17
 
18
18
  ### The ONLY two exceptions where a narrow stub is allowed
19
19
 
@@ -30,7 +30,7 @@ A feature is not done when it works — it's done when every surface it exposes
30
30
 
31
31
  | Coverage | Layer | Proves |
32
32
  |---|---|---|
33
- | **Logic** | `build` / `main` | The feature's functions do the right thing when called directly (real Manager, real storage, real IPC) |
33
+ | **Logic** | `build` / `main` | The feature's functions do the right thing when called directly (the real booted `omega`, real storage, real IPC) |
34
34
  | **UI** | `renderer` | The feature's interface is WIRED — a real event on the real DOM triggers the behavior and the visible result appears |
35
35
  | **End-to-end** | `boot` | The feature survives in the consumer's actual built bundle (extend the boot suite's `inspect` assertions) |
36
36
 
@@ -85,7 +85,7 @@ TEST_EXTENDED_MODE=true npx omega test build/config
85
85
 
86
86
  The target matches against the test file path. The source prefix scopes selection to framework-only or project-only tests — a prefixed target excludes the other source entirely:
87
87
 
88
- - `mgr:` — the **universal cross-framework alias** for "the manager's own tests" (framework-only). Works identically in @omega.js/desktop, BXM, UJM, and @omega.js/backend.
88
+ - `mgr:`: the **universal cross-framework alias** for "the framework's own tests" (framework-only). Works identically in @omega.js/desktop, @omega.js/extension, @omega.js/web, and @omega.js/backend.
89
89
  - `desktop:` / `framework:` — desktop-specific aliases for framework-only tests, equivalent to `mgr:`.
90
90
  - `project:` — consumer project tests only.
91
91
 
@@ -111,20 +111,20 @@ Anything an extended suite creates externally must be torn down in its `cleanup(
111
111
 
112
112
  ### `OMEGA_ENVIRONMENT=testing`, the one input a test run names
113
113
 
114
- Both @omega.js/desktop test runners (`runners/electron.js`, `runners/boot.js`) spawn their child with `OMEGA_ENVIRONMENT=testing`, the ONE environment input ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)), and nothing writes over an explicit one: the word a build baked into the artifact is the fallback for a packaged app, never an override ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). That powers `manager.isTesting()` (and the `Manager.isTesting()` static), the cross-context helper everything in @omega.js/desktop checks when it needs to behave differently in tests:
114
+ Both @omega.js/desktop test runners (`runners/electron.js`, `runners/boot.js`) spawn their child with `OMEGA_ENVIRONMENT=testing`, the ONE environment input ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)), and nothing writes over an explicit one: the word a build baked into the artifact is the fallback for a packaged app, never an override ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). That powers `omega.isTesting()` (and the build module's `isTesting()`), the cross-context helper everything in @omega.js/desktop checks when it needs to behave differently in tests:
115
115
 
116
116
  - `auto-updater` flips its idle threshold from 15min → 3s and its periodic tick from 60s → 500ms, AND short-circuits the native install-prompt dialog (so tests don't pop modal windows).
117
117
  - **Every BrowserWindow surfaces stealth** — named windows via `window-manager._surface()` AND raw `new BrowserWindow()` ones (e.g. a consumer's automation popup) via a global `browser-window-created` hook registered in `main.js` step 1a-ii. The shared recipe lives in `src/utils/stealth-window.js`: shown INACTIVE (keyboard focus never leaves your editor), opacity 0, click-through (`setIgnoreMouseEvents`), and raw windows get `show()` rerouted to `showInactive()` + `focus()` no-op'd — a test run never interrupts you, and a stray real click physically can't land in the app, while synthetic test input (`executeJavaScript`, `sendInputEvent`, CDP) is unaffected. **`webContents.focus()` is suppressed separately** (a global `web-contents-created` hook in the same main.js block): it bypasses the window-level patches — it's a different object whose `focus()` reaches the native window directly and makes the invisible window KEY, grabbing the keyboard mid-typing even under the accessory policy (which only prevents *launch* activation, not key-window steals). Consumers call it legitimately (e.g. address-bar focus on tab select), so it's no-op'd per-contents under the same predicate. Set **`OMEGA_TEST_SHOW=1`** to surface windows normally and watch a run live (the predicate is evaluated per window, so flipping it mid-run works). Deliberately NOT `hide()`/`minimize()`: occluded windows get throttled by Chromium (`requestAnimationFrame` pauses, `document.visibilityState` flips to `hidden`) — tests would exercise a DIFFERENT runtime, whereas an opacity-0 shown-inactive window renders and behaves identically to a visible one. See [windows.md](windows.md).
118
118
  - **App-level activation is suppressed too (macOS).** Launching a regular-policy app activates it — the menu bar and keyboard focus switch to the test process at launch even though every window surfaces inactive. Under the same stealth predicate (`src/utils/test-stealth.js` — Testing mode + `OMEGA_TEST_SHOW` unset), `main.js` (step 1a, before app ready) and the spawned test harness flip the app to the **accessory activation policy** (`app.dock.hide()` — the same switch `LSUIElement` bakes for packaged hidden-mode apps): the process never activates, never shows a dock icon, and never steals focus, while windows still render identically. `OMEGA_TEST_SHOW=1` restores normal activation along with visible windows. Verified by frontmost-app sampling across a full run: zero focus changes (previously four steals per run).
119
119
  - `main.js#initialize` isolates userData per environment: testing runs get `<userData> (Testing)` — **wiped at boot**, so every test run starts from a clean slate (post-run state stays on disk for inspection until the next run; set `OMEGA_TEST_KEEP_USERDATA=1` to skip the wipe). Dev runs get ` (Development)`; production is untouched. See [boot-sequence.md](boot-sequence.md).
120
120
  - **The main-layer harness exposes a CDP endpoint.** `test/harness/main-entry.js` appends `--remote-debugging-port=0` at require time (loopback-only, OS-assigned port) and publishes the resolved port as **`process.env.OMEGA_CDP_PORT`** before suites run (read from Chromium's `DevToolsActivePort` file; any value inherited from your shell is overwritten — that one points at your dev app, not the harness). Consumer suites can drive real browser automation against the harness Electron itself, e.g. `playwright-core`'s `connectOverCDP('http://127.0.0.1:' + process.env.OMEGA_CDP_PORT)`. Covered by `suites/main/harness-cdp.test.js`.
121
- - Other lib code can branch on `manager.isTesting()` to suppress dock bounce, login-item changes, OS protocol-handler registration, etc.
121
+ - Other lib code can branch on `omega.isTesting()` to suppress dock bounce, login-item changes, OS protocol-handler registration, etc.
122
122
 
123
123
  Consumers writing their own tests name the same input in their own runner, for example in `package.json`:
124
124
  ```json
125
125
  "test": "OMEGA_ENVIRONMENT=testing vitest"
126
126
  ```
127
- Then in your code, gate test-only behavior on `manager.isTesting()` instead of inventing yet another env var.
127
+ Then in your code, gate test-only behavior on `omega.isTesting()` instead of inventing yet another env var.
128
128
 
129
129
  ## Test discovery
130
130
 
@@ -170,14 +170,14 @@ module.exports = {
170
170
  layer: 'main', // 'build' | 'main' | 'renderer'
171
171
  description: 'storage (main)',
172
172
  cleanup: async (ctx) => { // runs after the last test
173
- ctx.manager.storage.clear();
173
+ ctx.omega.storage.clear();
174
174
  },
175
175
  tests: [
176
176
  {
177
177
  name: 'set + get round-trip',
178
178
  run: (ctx) => {
179
- ctx.manager.storage.set('hello', 'world');
180
- ctx.expect(ctx.manager.storage.get('hello')).toBe('world');
179
+ ctx.omega.storage.set('hello', 'world');
180
+ ctx.expect(ctx.omega.storage.get('hello')).toBe('world');
181
181
  },
182
182
  },
183
183
  {
@@ -232,7 +232,7 @@ module.exports = [
232
232
  | Layer | Where it runs | Use for |
233
233
  |---|---|---|
234
234
  | `build` | Plain Node | CLI, package.json, config schema, gulp tasks |
235
- | `main` | Spawned Electron main process | Manager init, lib modules, IPC, windows |
235
+ | `main` | Spawned Electron main process | `omega.initialize()`, lib modules, IPC, windows |
236
236
  | `renderer` | Hidden BrowserWindow: the framework's harness page by default, one of the project's own `src/views/` when the suite declares `view: '<name>'` | `window.desktop.*`, preload bridge, UI logic, your own views |
237
237
 
238
238
  The runner partitions test files by layer at discovery time. The build layer runs inline; the main layer spawns Electron once with all main suites and parses JSON-line stdout.
@@ -246,7 +246,7 @@ ctx.expect(actual) // Jest-compatible expect()
246
246
  ctx.state // shared object across tests in a suite/group
247
247
  ctx.layer // 'build' | 'main' | 'renderer'
248
248
  ctx.skip(reason) // skip from inside the test
249
- ctx.manager // (main layer only) the booted @omega.js/desktop Manager
249
+ ctx.omega // (main layer only) the booted @omega.js/desktop main-process instance
250
250
  ```
251
251
 
252
252
  ## expect() matchers
@@ -290,15 +290,15 @@ All test output is also teed (ANSI-stripped) to `<projectRoot>/logs/test.log`, t
290
290
  ## Test harness internals (main layer)
291
291
 
292
292
  - `runners/electron.js` spawns Electron with `harness/main-entry.js` as the app.
293
- - `harness/main-entry.js` boots Manager with `skipWindowCreation: true`, runs the suites, emits results via `__EM_TEST__{json}\n` lines on stdout.
293
+ - `harness/main-entry.js` boots `omega` with `skipWindowCreation: true`, runs the suites, emits results via `__OMEGA_TEST__{json}\n` lines on stdout (`TEST_EVENT_PREFIX`, [src/utils/test-events.js](../src/utils/test-events.js), the one prefix every harness writes and every runner reads).
294
294
  - The runner parses those lines and renders @omega.js/backend-style output.
295
295
  - stderr is always drained (otherwise the pipe fills and the harness blocks); printed only when `OMEGA_TEST_DEBUG=1`.
296
296
  - `ELECTRON_RUN_AS_NODE` is stripped from the spawn env (would otherwise make Electron behave as Node and break the harness).
297
- - **Consumer-scheme containment.** The consumer's `main.js` — where the real `protocol.handle('<brand.id>', …)` lives — never runs in this harness, so `brand://` URLs loaded by main-layer suites would be UNHANDLED. Chromium treats a load on an unhandled scheme as an *external protocol* and hands it to the OS — and if an installed copy of the app owns the scheme (e.g. `/Applications/Brand.app` on macOS, registered via its `Info.plist`), Launch Services launches the installed production app mid-test-run. The harness contains this two ways after Manager boots: (1) it registers a stub handler for the consumer's brand scheme (read from `<cwd>/config/omega.json5`) on the default session, so `brand://` loads commit in-process as a blank page; (2) it denies the `openExternal` permission on the default session and every session created after it (partitions included), so no navigation can hand ANY scheme to the OS during a test run. Suites that need real page content for `brand://` URLs belong in the boot layer, where the real app (and its real protocol handler) runs. A main-layer suite that genuinely needs its OWN handler for the brand scheme must call `protocol.unhandle(brand.id)` first — the harness stub holds the scheme on the default session.
297
+ - **Consumer-scheme containment.** The consumer's `main.js` (where the real `protocol.handle('<brand.id>', …)` lives) never runs in this harness, so `brand://` URLs loaded by main-layer suites would be UNHANDLED. Chromium treats a load on an unhandled scheme as an *external protocol* and hands it to the OS: and if an installed copy of the app owns the scheme (e.g. `/Applications/Brand.app` on macOS, registered via its `Info.plist`), Launch Services launches the installed production app mid-test-run. The harness contains this two ways after `omega` boots: (1) it registers a stub handler for the consumer's brand scheme (read from `<cwd>/config/omega.json5`) on the default session, so `brand://` loads commit in-process as a blank page; (2) it denies the `openExternal` permission on the default session and every session created after it (partitions included), so no navigation can hand ANY scheme to the OS during a test run. Suites that need real page content for `brand://` URLs belong in the boot layer, where the real app (and its real protocol handler) runs. A main-layer suite that genuinely needs its OWN handler for the brand scheme must call `protocol.unhandle(brand.id)` first: the harness stub holds the scheme on the default session.
298
298
 
299
299
  ## A test run never touches the OS keychain, and a blocked boot reports
300
300
 
301
- The harness resolves auth persistence to the **`none`** strategy on every layer, main and boot alike, before any config is read: a brand that declares `omega.authPersistence: 'safeStorage'` still runs its tests with Firebase auth in memory, because the lanes never sign a real user in. That is a hard rule, not a nicety. The boot lane spawns the raw, unsigned `Electron` binary, which carries no keychain ACL, so one `safeStorage` read parks the entire run behind a macOS SecurityAgent prompt ([#907](https://github.com/Omega-JS-Stack/omega/issues/907)). ONE signal answers "is this a test run" on both layers, `manager.isTesting()`: the boot lane boots the consumer's PRODUCTION artifact, and the word baked into it no longer writes over the `OMEGA_ENVIRONMENT=testing` the runner spawned it with ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)), so the booted app reports the lane it is running in. And since a boot can block long before `main.js` requires the harness (where the per-test timeout lives), the boot runner carries its own budget, measured as SILENCE: every harness line rearms it, so a suite that legitimately runs longer keeps going, and a boot that produces no harness output for 60s (`OMEGA_TEST_BOOT_TIMEOUT_MS` overrides) counts its tests failed, prints `✗ boot: no harness output after 60s; last runtime.log line: "<line>"` from the booted app's `logs/runtime.log`, and ends the child instead of hanging `npx omega test`.
301
+ The harness resolves auth persistence to the **`none`** strategy on every layer, main and boot alike, before any config is read: a brand that declares `omega.authPersistence: 'safeStorage'` still runs its tests with Firebase auth in memory, because the lanes never sign a real user in. That is a hard rule, not a nicety. The boot lane spawns the raw, unsigned `Electron` binary, which carries no keychain ACL, so one `safeStorage` read parks the entire run behind a macOS SecurityAgent prompt ([#907](https://github.com/Omega-JS-Stack/omega/issues/907)). ONE signal answers "is this a test run" on both layers, `omega.isTesting()`: the boot lane boots the consumer's PRODUCTION artifact, and the word baked into it no longer writes over the `OMEGA_ENVIRONMENT=testing` the runner spawned it with ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)), so the booted app reports the lane it is running in. And since a boot can block long before `main.js` requires the harness (where the per-test timeout lives), the boot runner carries its own budget, measured as SILENCE: every harness line rearms it, so a suite that legitimately runs longer keeps going, and a boot that produces no harness output for 60s (`OMEGA_TEST_BOOT_TIMEOUT_MS` overrides) counts its tests failed, prints `✗ boot: no harness output after 60s; last runtime.log line: "<line>"` from the booted app's `logs/runtime.log`, and ends the child instead of hanging `npx omega test`.
302
302
 
303
303
  ## Writing consumer tests
304
304
 
@@ -314,7 +314,7 @@ module.exports = {
314
314
  {
315
315
  name: 'storage starts empty',
316
316
  run: (ctx) => {
317
- ctx.expect(ctx.manager.storage.get('user')).toBeUndefined();
317
+ ctx.expect(ctx.omega.storage.get('user')).toBeUndefined();
318
318
  },
319
319
  },
320
320
  ],
package/docs/themes.md CHANGED
@@ -87,13 +87,13 @@ theme: {
87
87
  }
88
88
  ```
89
89
 
90
- ## Appearance (light / dark / system) — `manager.theme`
90
+ ## Appearance (light / dark / system): `omega.theme`
91
91
 
92
92
  @omega.js/desktop owns appearance at runtime. `config.theme.appearance` is only the **app default**; the resolved appearance is applied and kept live by the theme lib:
93
93
 
94
94
  - **`'system'` (default)** follows the OS preference **live** — when the OS flips, every page updates without a reload or restart.
95
95
  - **`'light'` / `'dark'`** are explicit overrides.
96
- - A user's runtime choice (`manager.theme.set(...)`) is **persisted in `manager.storage`** (`theme.appearance`) and wins over the config default on every boot.
96
+ - A user's runtime choice (`omega.theme.set(...)`) is **persisted in `omega.storage`** (`theme.appearance`) and wins over the config default on every boot.
97
97
 
98
98
  ### How it propagates
99
99
 
@@ -105,10 +105,10 @@ The applier is **opt-in by presence**: it only manages pages whose `<html>` alre
105
105
 
106
106
  ```js
107
107
  // Main
108
- manager.theme.get(); // 'system' | 'light' | 'dark' (the chosen source)
109
- manager.theme.resolved(); // 'light' | 'dark' (what's showing)
110
- manager.theme.set('dark'); // apply + persist (throws on invalid values)
111
- const unsub = manager.theme.onChange(({ source, resolved }) => { ... });
108
+ omega.theme.get(); // 'system' | 'light' | 'dark' (the chosen source)
109
+ omega.theme.resolved(); // 'light' | 'dark' (what's showing)
110
+ omega.theme.set('dark'); // apply + persist (throws on invalid values)
111
+ const unsub = omega.theme.onChange(({ source, resolved }) => { ... });
112
112
 
113
113
  // Renderer (any page with the @omega.js/desktop preload)
114
114
  await window.desktop.theme.get(); // { source, resolved }
@@ -120,7 +120,7 @@ Main also broadcasts `desktop:theme:changed { source, resolved }` to BrowserWind
120
120
 
121
121
  ### Declarative controls
122
122
 
123
- Any element with `data-omega-theme-set` becomes a theme switch (wired by the renderer Manager's initialize — event-delegated, so late-rendered controls work):
123
+ Any element with `data-omega-theme-set` becomes a theme switch (wired by the renderer's `omega.initialize()`, event-delegated, so late-rendered controls work):
124
124
 
125
125
  ```html
126
126
  <button data-omega-theme-set="light">Day</button>
package/docs/tooltips.md CHANGED
@@ -52,7 +52,7 @@ control and put the tooltip on the wrapper:
52
52
  ## The rest of Bootstrap's JS
53
53
 
54
54
  The full namespace is exposed at **`window.bootstrap`** (and
55
- `manager.bootstrap`) — `Tooltip`, `Popover`, `Collapse`, `Dropdown`, `Modal`,
55
+ `omega.bootstrap`): `Tooltip`, `Popover`, `Collapse`, `Dropdown`, `Modal`,
56
56
  `Offcanvas`, `Tab`, `Toast`, `Alert`, `Button`, `Carousel`, `ScrollSpy`. Only
57
57
  tooltips are auto-initialized; the other components' standard **data-api**
58
58
  works out of the box on plain Bootstrap markup (e.g.
@@ -94,6 +94,6 @@ runs from a preload, e.g. the test harness).
94
94
 
95
95
  - `src/test/suites/renderer/tooltips.test.js` — bundle loads, auto-init on
96
96
  insertion, live retitle, dispose-on-removal, tip cleanup. (The harness wires
97
- the renderer Manager in the preload world — see the suite header for the
97
+ the renderer instance in the preload world: see the suite header for the
98
98
  world-split notes; single-world hover behavior is covered by consumer boot
99
99
  suites.)
package/docs/tray.md CHANGED
@@ -4,19 +4,19 @@ File-based tray/menubar. @omega.js/desktop looks for `src/integrations/tray/inde
4
4
 
5
5
  ## Config
6
6
 
7
- No config block. Path is conventional: `src/integrations/tray/index.js`. To opt out, call `manager.tray.disable()` from your main entry — idempotent, tears down any existing Tray.
7
+ No config block. Path is conventional: `src/integrations/tray/index.js`. To opt out, call `omega.tray.disable()` from your main entry: idempotent, tears down any existing Tray.
8
8
 
9
9
  ## Definition file
10
10
 
11
11
  ```js
12
12
  // src/integrations/tray/index.js
13
- module.exports = ({ manager, tray }) => {
13
+ module.exports = ({ omega, tray }) => {
14
14
  // @omega.js/desktop auto-resolves the tray icon from config/icons/<platform>/tray.png at build
15
15
  // time, so explicit tray.icon() is OPTIONAL. Call it only to override.
16
16
  // Note: on macOS, if you pass your own path, the filename MUST end in
17
17
  // `Template.png` for the OS to auto-invert it in dark mode.
18
18
  // tray.icon('src/assets/icons/my-trayTemplate.png');
19
- tray.tooltip(manager.config?.app?.productName);
19
+ tray.tooltip(omega.config?.app?.productName);
20
20
 
21
21
  // Easiest: start from @omega.js/desktop's default template.
22
22
  tray.useDefaults();
@@ -25,7 +25,7 @@ module.exports = ({ manager, tray }) => {
25
25
  tray.insertAfter('open', {
26
26
  id: 'dashboard',
27
27
  label: 'Open Dashboard',
28
- click: () => manager.windows.show('dashboard'),
28
+ click: () => omega.windows.show('dashboard'),
29
29
  });
30
30
  tray.update('open', { label: 'Show Window' });
31
31
  tray.remove('website');
@@ -47,7 +47,7 @@ tray.clear() // start over
47
47
 
48
48
  ## Id-path API
49
49
 
50
- Same shape across menu / tray / context-menu. Available **during definition** (on the `tray` builder arg) AND **at runtime** on `manager.tray`:
50
+ Same shape across menu / tray / context-menu. Available **during definition** (on the `tray` builder arg) AND **at runtime** on `omega.tray`:
51
51
 
52
52
  ```js
53
53
  .find(idPath) // live descriptor or null
@@ -69,8 +69,8 @@ Tray ids are **flat** — no `tray/` prefix (the lib namespace is implicit). For
69
69
  | ID | Item |
70
70
  |---|---|
71
71
  | `title` | Disabled label showing the app name |
72
- | `open` | "Open `<app>`" — calls `manager.windows.show('main')` |
73
- | `check-for-updates` | Wired to `manager.autoUpdater` (label updates dynamically) |
72
+ | `open` | "Open `<app>`": calls `omega.windows.show('main')` |
73
+ | `check-for-updates` | Wired to `omega.autoUpdater` (label updates dynamically) |
74
74
  | `website` | Visit `brand.url` (only present if configured) |
75
75
  | `quit` | Quit the app |
76
76
 
@@ -84,9 +84,9 @@ tray.item({ id: 'account', label: 'Account', submenu: [
84
84
  { id: 'sign-out', label: 'Sign out', click: () => {} },
85
85
  ]});
86
86
 
87
- manager.tray.find('account/sign-out');
88
- manager.tray.update('account/sign-out', { enabled: false });
89
- manager.tray.appendTo('account', { id: 'profile', label: 'Profile' });
87
+ omega.tray.find('account/sign-out');
88
+ omega.tray.update('account/sign-out', { enabled: false });
89
+ omega.tray.appendTo('account', { id: 'profile', label: 'Profile' });
90
90
  ```
91
91
 
92
92
  ## Item descriptors
@@ -103,30 +103,30 @@ Mirror Electron's [`MenuItemConstructorOptions`](https://www.electronjs.org/docs
103
103
  | `click` | function | Wrapped to swallow errors so a bad handler can't kill the menu |
104
104
  | `submenu` | array | Recursively resolved with the same conveniences |
105
105
 
106
- ## Runtime API on `manager.tray`
106
+ ## Runtime API on `omega.tray`
107
107
 
108
108
  ```js
109
- manager.tray.refresh() // re-evaluate dynamic state and re-render
110
- manager.tray.define(fn) // replace the whole definition at runtime
111
- manager.tray.disable() // tear down + stop responding (idempotent)
112
- manager.tray.setIcon(path)
113
- manager.tray.setTooltip(text)
114
- manager.tray.addItem(descriptor) // append (preserves existing items)
115
- manager.tray.clearItems()
116
- manager.tray.destroy() // tear down (mostly for tests)
109
+ omega.tray.refresh() // re-evaluate dynamic state and re-render
110
+ omega.tray.define(fn) // replace the whole definition at runtime
111
+ omega.tray.disable() // tear down + stop responding (idempotent)
112
+ omega.tray.setIcon(path)
113
+ omega.tray.setTooltip(text)
114
+ omega.tray.addItem(descriptor) // append (preserves existing items)
115
+ omega.tray.clearItems()
116
+ omega.tray.destroy() // tear down (mostly for tests)
117
117
 
118
118
  // Id-path API — same as listed above.
119
- manager.tray.find('quit')
120
- manager.tray.update('quit', { label: 'Goodbye' })
121
- manager.tray.remove('website')
122
- manager.tray.insertAfter('open', { id: 'preferences', label: 'Preferences...', click: ... })
123
- manager.tray.hide('check-for-updates')
119
+ omega.tray.find('quit')
120
+ omega.tray.update('quit', { label: 'Goodbye' })
121
+ omega.tray.remove('website')
122
+ omega.tray.insertAfter('open', { id: 'preferences', label: 'Preferences...', click: ... })
123
+ omega.tray.hide('check-for-updates')
124
124
 
125
125
  // Inspection
126
- manager.tray.getItems() // shallow copy of raw descriptors
127
- manager.tray.getIcon()
128
- manager.tray.getTooltip()
129
- manager.tray.isRendered()
126
+ omega.tray.getItems() // shallow copy of raw descriptors
127
+ omega.tray.getIcon()
128
+ omega.tray.getTooltip()
129
+ omega.tray.isRendered()
130
130
  ```
131
131
 
132
132
  ## Common patterns
@@ -135,8 +135,8 @@ manager.tray.isRendered()
135
135
 
136
136
  ```js
137
137
  // in your renderer/main code, after sign-in:
138
- manager.storage.set('user', { ... });
139
- manager.tray.refresh(); // dynamic-label functions re-evaluate
138
+ omega.storage.set('user', { ... });
139
+ omega.tray.refresh(); // dynamic-label functions re-evaluate
140
140
  ```
141
141
 
142
142
  ### Hide updater item if you ship without auto-update
@@ -153,7 +153,7 @@ module.exports = ({ tray }) => {
153
153
  ### Replace the entire tray at runtime
154
154
 
155
155
  ```js
156
- manager.tray.define(({ manager, tray }) => {
156
+ omega.tray.define(({ omega, tray }) => {
157
157
  tray.icon('icons/dark-mode.png');
158
158
  tray.item({ id: 'x', label: 'New layout', click: ... });
159
159
  });
package/docs/usage.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Usage
2
2
 
3
- Tracks app-launch + hours-of-use stats. Sister of legacy @omega.js/desktop's Usage library, but uses `manager.storage` instead of a separate electron-store.
3
+ Tracks app-launch + hours-of-use stats. Sister of legacy @omega.js/desktop's Usage library, but uses `omega.storage` instead of a separate electron-store.
4
4
 
5
5
  ## What's tracked
6
6
 
7
7
  ```js
8
- manager.usage.opens() // total app launches
9
- manager.usage.hoursTotal() // cumulative hours-of-use across clean exits
10
- manager.usage.hoursThisSession() // live, computed from session start
11
- manager.usage.installedAt() // ISO timestamp of first launch
12
- manager.usage.toJSON() // all of the above as a structured-cloneable object
8
+ omega.usage.opens() // total app launches
9
+ omega.usage.hoursTotal() // cumulative hours-of-use across clean exits
10
+ omega.usage.hoursThisSession() // live, computed from session start
11
+ omega.usage.installedAt() // ISO timestamp of first launch
12
+ omega.usage.toJSON() // all of the above as a structured-cloneable object
13
13
  ```
14
14
 
15
15
  ## How it accumulates
@@ -51,7 +51,7 @@ const snap = await window.desktop.usage.get();
51
51
 
52
52
  ## Why not just use app-state?
53
53
 
54
- `app-state.js` already tracks `launchCount` (= opens). We could fold these in. But `app-state` is concerned with first-launch / crash-sentinel / version-change semantics — `usage` is concerned with telemetry. Keeping them separate keeps each module focused. Both write to disjoint keys in `manager.storage`.
54
+ `app-state.js` already tracks `launchCount` (= opens). We could fold these in. But `app-state` is concerned with first-launch / crash-sentinel / version-change semantics: `usage` is concerned with telemetry. Keeping them separate keeps each module focused. Both write to disjoint keys in `omega.storage`.
55
55
 
56
56
  ## Tests
57
57
 
package/docs/verts.md CHANGED
@@ -12,7 +12,7 @@ zero consumer JS, same element vocabulary as the web `verts/unit` section and
12
12
 
13
13
  ## What the wiring does
14
14
 
15
- `renderer.js _wireAds` (runs inside `manager.initialize()`, same liveness
15
+ `renderer.js _wireAds` (runs inside `omega.initialize()`, same liveness
16
16
  model as the FontAwesome/tooltip wiring) binds every `[data-omega-vert]`
17
17
  element present at init AND inserted later (MutationObserver), marking bound
18
18
  hosts `data-omega-vert-bound="house"`. Everything after the bind lives in the
package/docs/windows.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Windows
2
2
 
3
- **Lazy named-window registry.** @omega.js/desktop does NOT auto-create any window. Your `main.js` calls `manager.windows.create('main', { show: !startup.isLaunchHidden() })` from inside `manager.initialize().then(() => { ... })`. Always create `main` — its presence in the registry is what lets @omega.js/desktop's `app.on('activate')` (macOS dock click) and `app.on('second-instance')` (win/linux re-launch) handlers surface UI when the user double-clicks the running app. In hidden launches, pass `show: false` to keep the window invisible until something explicitly calls `windows.show('main')`. Use the registry for the common case (named, persistent, integrated windows). For one-off windows (a toast, a print preview), use `new BrowserWindow()` directly — `window-manager` doesn't get in the way.
3
+ **Lazy named-window registry.** @omega.js/desktop does NOT auto-create any window. Your `main.js` calls `omega.windows.create('main', { show: !startup.isLaunchHidden() })` from inside `omega.initialize().then(() => { ... })`. Always create `main`: its presence in the registry is what lets @omega.js/desktop's `app.on('activate')` (macOS dock click) and `app.on('second-instance')` (win/linux re-launch) handlers surface UI when the user double-clicks the running app. In hidden launches, pass `show: false` to keep the window invisible until something explicitly calls `windows.show('main')`. Use the registry for the common case (named, persistent, integrated windows). For one-off windows (a toast, a print preview), use `new BrowserWindow()` directly, `window-manager` doesn't get in the way.
4
4
 
5
5
  ## Re-surface on user re-launch
6
6
 
@@ -14,20 +14,20 @@ Both handlers are no-ops if `main` isn't in the registry. So consumers who genui
14
14
  ## API
15
15
 
16
16
  ```js
17
- await manager.windows.create('main', overrides?) // canonical entry point
18
- await manager.windows.createNamed('main', mgr, opts?) // identical; .create() is sugar
19
- manager.windows.get('main') // BrowserWindow | null
20
- manager.windows.show('main') // show + focus + auto app.dock.show()
21
- manager.windows.hide('main')
22
- manager.windows.close('main') // force-close (bypasses hideOnClose)
23
- manager.windows.list() // string[] of currently-open names
17
+ await omega.windows.create('main', overrides?) // canonical entry point
18
+ await omega.windows.createNamed('main', mgr, opts?) // identical; .create() is sugar
19
+ omega.windows.get('main') // BrowserWindow | null
20
+ omega.windows.show('main') // show + focus + auto app.dock.show()
21
+ omega.windows.hide('main')
22
+ omega.windows.close('main') // force-close (bypasses hideOnClose)
23
+ omega.windows.list() // string[] of currently-open names
24
24
  ```
25
25
 
26
26
  `create()` is single-instance: a second call with the same name returns the existing window and focuses it (no double-create).
27
27
 
28
28
  ## Defaults
29
29
 
30
- No JSON config required. @omega.js/desktop bakes in sensible defaults so `manager.windows.create('main')` "just works":
30
+ No JSON config required. @omega.js/desktop bakes in sensible defaults so `omega.windows.create('main')` "just works":
31
31
 
32
32
  | Window | Defaults |
33
33
  |---|---|
@@ -37,8 +37,8 @@ No JSON config required. @omega.js/desktop bakes in sensible defaults so `manage
37
37
  Override at the call site:
38
38
 
39
39
  ```js
40
- manager.windows.create('main', { width: 1280, height: 800 });
41
- manager.windows.create('settings', { width: 600, height: 480 });
40
+ omega.windows.create('main', { width: 1280, height: 800 });
41
+ omega.windows.create('settings', { width: 600, height: 480 });
42
42
  ```
43
43
 
44
44
  ## Config (optional)
@@ -60,7 +60,7 @@ Per-window keys:
60
60
  | `view` | `main` | `<name>` | Folder under `src/views/`. Loads `dist/views/<view>/index.html`. |
61
61
  | `width` / `height` | 1024 / 720 | 800 / 600 | Initial size (overridden by saved bounds if `persistBounds: true`). |
62
62
  | `minWidth` / `minHeight` | 400 / 300 | 400 / 300 | |
63
- | `show` | `true` | `true` | Auto-show on `ready-to-show`. `false` keeps the window hidden until `manager.windows.show()`. |
63
+ | `show` | `true` | `true` | Auto-show on `ready-to-show`. `false` keeps the window hidden until `omega.windows.show()`. |
64
64
  | `hideOnClose` | `true` | `false` | Discord-style: X click hides instead of closes. See "Hide-on-close" below. |
65
65
  | `title` | `app.productName` | `app.productName` | Window title. |
66
66
  | `backgroundColor` | `#ffffff` | `#ffffff` | Background color before the page loads. |
@@ -96,15 +96,15 @@ The `main` window's X button **hides instead of closes** by default. Real quit o
96
96
  - Menu Quit (`main/quit` on mac, `file/quit` on win/linux)
97
97
  - Tray Quit (`quit` item)
98
98
  - Auto-updater install (`autoUpdater.installNow()`)
99
- - Programmatic `manager.quit({ force: true })`
99
+ - Programmatic `omega.quit({ force: true })`
100
100
 
101
101
  The window-manager close handler checks three flags before deciding to swallow vs let through:
102
102
 
103
103
  | Flag | Set by | Means |
104
104
  |---|---|---|
105
- | `manager._allowQuit` | `manager.quit({ force: true })`, `autoUpdater.installNow()` | Programmatic force — let the close go through. |
106
- | `manager._isQuitting` | `app.on('before-quit')` (every quit path Electron knows about) | App is quitting — let close events flow naturally. |
107
- | `win._emForceClose` | `manager.windows.close(name)` | Per-window override. |
105
+ | `omega._allowQuit` | `omega.quit({ force: true })`, `autoUpdater.installNow()` | Programmatic force: let the close go through. |
106
+ | `omega._isQuitting` | `app.on('before-quit')` (every quit path Electron knows about) | App is quitting: let close events flow naturally. |
107
+ | `win._emForceClose` | `omega.windows.close(name)` | Per-window override. |
108
108
 
109
109
  Other named windows default to `hideOnClose: false` (X actually closes). Override per window via config or call-site overrides.
110
110
 
@@ -121,27 +121,27 @@ Every named window's position and size persist to storage on resize / move / max
121
121
 
122
122
  ## macOS dock auto-show
123
123
 
124
- When `LSUIElement: true` is baked at build time (`startup.mode: 'hidden'`), the app launches with **no dock icon, no Cmd+Tab, no taskbar**. The first time `manager.windows.create()` or `manager.windows.show()` runs, @omega.js/desktop calls `app.dock.show()` automatically — the dock icon appears alongside the window.
124
+ When `LSUIElement: true` is baked at build time (`startup.mode: 'hidden'`), the app launches with **no dock icon, no Cmd+Tab, no taskbar**. The first time `omega.windows.create()` or `omega.windows.show()` runs, @omega.js/desktop calls `app.dock.show()` automatically: the dock icon appears alongside the window.
125
125
 
126
- **And the inverse**: for `startup.mode: 'hidden'` apps, when the LAST visible named window hides (hide-on-close X, `windows.hide()`, any consumer `win.hide()`), @omega.js/desktop calls `app.dock.hide()` again — the app returns to its fully-invisible posture, dock and UI appearing and vanishing together. Normal-mode apps keep their dock icon for life; quit paths are untouched (`manager._isQuitting` guard).
126
+ **And the inverse**: for `startup.mode: 'hidden'` apps, when the LAST visible named window hides (hide-on-close X, `windows.hide()`, any consumer `win.hide()`), @omega.js/desktop calls `app.dock.hide()` again: the app returns to its fully-invisible posture, dock and UI appearing and vanishing together. Normal-mode apps keep their dock icon for life; quit paths are untouched (`omega._isQuitting` guard).
127
127
 
128
128
  This means agent / menubar apps can stay completely invisible until the user explicitly asks for UI:
129
129
 
130
130
  ```js
131
- manager.initialize().then(() => {
131
+ omega.initialize().then(() => {
132
132
  // Don't call windows.create() here — app stays invisible.
133
133
  // Surface UI later when something warrants it:
134
- manager.tray.update('open', { click: () => manager.windows.create('main') });
134
+ omega.tray.update('open', { click: () => omega.windows.create('main') });
135
135
  });
136
136
  ```
137
137
 
138
138
  ## Auto-attach context-menu
139
139
 
140
- Every window created via `manager.windows.create()` is automatically wired up with the consumer's `src/integrations/context-menu/index.js` (see [context-menu.md](context-menu.md)). Idempotent per webContents (uses a WeakSet). For windows you create directly with `new BrowserWindow()`, call `manager.contextMenu.attach(win.webContents)` manually.
140
+ Every window created via `omega.windows.create()` is automatically wired up with the consumer's `src/integrations/context-menu/index.js` (see [context-menu.md](context-menu.md)). Idempotent per webContents (uses a WeakSet). For windows you create directly with `new BrowserWindow()`, call `omega.contextMenu.attach(win.webContents)` manually.
141
141
 
142
142
  ## Testing mode: stealth surfacing
143
143
 
144
- When `manager.isTesting()` (i.e. under `npx omega test`), every surfacing path in this lib — `ready-to-show`, `windows.show()`, the create-dedup focus — goes **stealth** instead of `win.show()`: `_surface()` applies the shared recipe from `src/utils/stealth-window.js` and surfaces via `showInactive()`, with no `win.focus()`/dock surfacing. **The full stealth story lives in [test-framework.md](test-framework.md) (SSOT)** — the recipe and why it's not `hide()`/`minimize()`, the raw-window `browser-window-created` hook, `webContents.focus()` suppression, macOS app-level activation suppression, and the **`OMEGA_TEST_SHOW=1`** opt-out. Covered by `suites/main/stealth-window.test.js`.
144
+ When `omega.isTesting()` (i.e. under `npx omega test`), every surfacing path in this lib (`ready-to-show`, `windows.show()`, the create-dedup focus) goes **stealth** instead of `win.show()`: `_surface()` applies the shared recipe from `src/utils/stealth-window.js` and surfaces via `showInactive()`, with no `win.focus()`/dock surfacing. **The full stealth story lives in [test-framework.md](test-framework.md) (SSOT)**: the recipe and why it's not `hide()`/`minimize()`, the raw-window `browser-window-created` hook, `webContents.focus()` suppression, macOS app-level activation suppression, and the **`OMEGA_TEST_SHOW=1`** opt-out. Covered by `suites/main/stealth-window.test.js`.
145
145
 
146
146
  ## Platform behavior
147
147
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omega.js/desktop",
3
- "version": "0.51.0",
3
+ "version": "0.53.0",
4
4
  "description": "OMEGA desktop framework — build, test, and package Electron apps for macOS, Windows, and Linux",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -23,7 +23,6 @@
23
23
  "./lib/context-menu": "./dist/lib/context-menu.js",
24
24
  "./lib/deep-link": "./dist/lib/deep-link.js",
25
25
  "./lib/ipc": "./dist/lib/ipc.js",
26
- "./lib/logger": "./dist/lib/logger.js",
27
26
  "./lib/logger-lite": "./dist/lib/logger-lite.js",
28
27
  "./lib/menu": "./dist/lib/menu.js",
29
28
  "./lib/protocol": "./dist/lib/protocol.js",
@@ -33,7 +32,7 @@
33
32
  "./lib/storage": "./dist/lib/storage.js",
34
33
  "./lib/templating": "./dist/lib/templating.js",
35
34
  "./lib/tray": "./dist/lib/tray.js",
36
- "./lib/client-bridge": "./dist/lib/client-bridge.js",
35
+ "./lib/auth": "./dist/lib/auth.js",
37
36
  "./lib/window-manager": "./dist/lib/window-manager.js",
38
37
  "./cli": "./dist/cli-run.js",
39
38
  "./ensure-target": "./dist/commands/lib/ensure-target.js",
@@ -155,7 +154,7 @@
155
154
  "@fortawesome/fontawesome-free": "^7.3.0",
156
155
  "@inquirer/prompts": "^8.5.2",
157
156
  "@octokit/rest": "^22.0.1",
158
- "@omega.js/client": "0.51.0",
157
+ "@omega.js/client": "0.53.0",
159
158
  "@popperjs/core": "^2.11.8",
160
159
  "@sentry/electron": "^7.13.0",
161
160
  "chalk": "^5.6.2",