@omega.js/desktop 0.52.0 → 0.54.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 (345) hide show
  1. package/README.md +53 -48
  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-run.js +4 -1
  26. package/dist/cli.js +3 -3
  27. package/dist/commands/build.js +2 -2
  28. package/dist/commands/cdp/capture.js +2 -2
  29. package/dist/commands/cdp/client.js +1 -1
  30. package/dist/commands/cdp/quit.js +2 -2
  31. package/dist/commands/cdp/relaunch.js +2 -2
  32. package/dist/commands/cdp/theme.js +1 -1
  33. package/dist/commands/cdp.js +1 -1
  34. package/dist/commands/clean.js +4 -5
  35. package/dist/commands/deploy.js +4 -4
  36. package/dist/commands/dev.js +25 -0
  37. package/dist/commands/finalize-release.js +4 -4
  38. package/dist/commands/launch.js +2 -2
  39. package/dist/commands/lib/deploy-precheck.js +3 -3
  40. package/dist/commands/lib/ensure-target.js +18 -23
  41. package/dist/commands/lib/migrate.js +17 -0
  42. package/dist/commands/logs.js +1 -1
  43. package/dist/commands/package.js +2 -2
  44. package/dist/commands/publish.js +2 -2
  45. package/dist/commands/release.js +4 -4
  46. package/dist/commands/runner.js +11 -11
  47. package/dist/commands/sign-windows.js +5 -5
  48. package/dist/commands/test.js +8 -8
  49. package/dist/commands/update.js +7 -6
  50. package/dist/commands/validate-certs.js +4 -4
  51. package/dist/commands/version.js +3 -3
  52. package/dist/defaults/.github/workflows/build.yml +18 -18
  53. package/dist/defaults/_.gitignore +0 -2
  54. package/dist/defaults/_mas/README.md +3 -3
  55. package/dist/defaults/config/certs/README.md +1 -1
  56. package/dist/defaults/config/omega.json5 +43 -43
  57. package/dist/defaults/docs/README.md +3 -3
  58. package/dist/defaults/gulpfile.js +1 -1
  59. package/dist/defaults/hooks/build/post.js +2 -2
  60. package/dist/defaults/hooks/build/pre.js +2 -2
  61. package/dist/defaults/hooks/deploy/pre.js +1 -1
  62. package/dist/defaults/hooks/notarize/post.js +2 -2
  63. package/dist/defaults/hooks/release/post.js +2 -2
  64. package/dist/defaults/hooks/release/pre.js +2 -2
  65. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  66. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  67. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  68. package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
  69. package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
  70. package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
  71. package/dist/defaults/src/integrations/context-menu/index.js +13 -13
  72. package/dist/defaults/src/integrations/menu/index.js +8 -8
  73. package/dist/defaults/src/integrations/tray/index.js +12 -12
  74. package/dist/defaults/src/main.js +5 -7
  75. package/dist/defaults/src/preload.js +4 -6
  76. package/dist/defaults/test/README.md +5 -5
  77. package/dist/defaults/test/_init.js +1 -1
  78. package/dist/gulp/main.js +9 -10
  79. package/dist/gulp/tasks/audit.js +11 -14
  80. package/dist/gulp/tasks/build-config.js +8 -8
  81. package/dist/gulp/tasks/bundle.js +16 -16
  82. package/dist/gulp/tasks/defaults.js +3 -3
  83. package/dist/gulp/tasks/distribute.js +2 -2
  84. package/dist/gulp/tasks/html.js +9 -9
  85. package/dist/gulp/tasks/package-quick.js +3 -3
  86. package/dist/gulp/tasks/package.js +3 -3
  87. package/dist/gulp/tasks/release.js +3 -3
  88. package/dist/gulp/tasks/sass.js +6 -6
  89. package/dist/gulp/tasks/serve.js +4 -4
  90. package/dist/hooks/notarize-artifacts.js +1 -1
  91. package/dist/hooks/notarize.js +1 -1
  92. package/dist/index.js +5 -8
  93. package/dist/lib/_environment-mixin.js +50 -0
  94. package/dist/lib/_lifecycle-mixin.js +45 -0
  95. package/dist/lib/analytics.js +33 -35
  96. package/dist/lib/app-state.js +14 -14
  97. package/dist/lib/auth-flow.js +18 -18
  98. package/dist/lib/auth-persistence.js +12 -12
  99. package/dist/lib/auth.js +421 -0
  100. package/dist/lib/auto-updater.js +49 -49
  101. package/dist/lib/context-menu.js +13 -13
  102. package/dist/lib/context.js +19 -19
  103. package/dist/lib/deep-link.js +34 -34
  104. package/dist/lib/fontawesome.js +5 -5
  105. package/dist/lib/ipc.js +4 -4
  106. package/dist/lib/menu.js +25 -25
  107. package/dist/lib/protocol.js +5 -5
  108. package/dist/lib/remote-config.js +22 -22
  109. package/dist/lib/remote-scripts.js +21 -21
  110. package/dist/lib/restart-manager/index.js +29 -29
  111. package/dist/lib/restart-manager/install.js +1 -1
  112. package/dist/lib/restart-manager/protocol.js +1 -1
  113. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  114. package/dist/lib/sign-helpers/sign-events.js +1 -1
  115. package/dist/lib/startup.js +18 -13
  116. package/dist/lib/storage.js +10 -10
  117. package/dist/lib/templating.js +16 -16
  118. package/dist/lib/theme.js +10 -10
  119. package/dist/lib/tray.js +27 -27
  120. package/dist/lib/usage.js +11 -11
  121. package/dist/lib/window-manager.js +26 -26
  122. package/dist/main.js +399 -483
  123. package/dist/preload.js +236 -176
  124. package/dist/renderer.js +417 -391
  125. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  126. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  127. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  128. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  129. package/dist/test/harness/boot-entry.js +22 -20
  130. package/dist/test/harness/main-entry.js +31 -30
  131. package/dist/test/harness/renderer-entry.js +5 -5
  132. package/dist/test/harness/renderer-preload.js +137 -141
  133. package/dist/test/index.js +10 -10
  134. package/dist/test/runner.js +2 -2
  135. package/dist/test/runners/boot.js +7 -6
  136. package/dist/test/runners/electron.js +3 -2
  137. package/dist/test/runners/render-event.js +2 -2
  138. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  139. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  140. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  141. package/dist/test/suites/boot/theme.test.js +13 -13
  142. package/dist/test/suites/build/audit.test.js +21 -8
  143. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  144. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  145. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  146. package/dist/test/suites/build/brand-scss.test.js +1 -1
  147. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  148. package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
  149. package/dist/test/suites/build/cli.test.js +30 -2
  150. package/dist/test/suites/build/config-schema.test.js +5 -5
  151. package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
  152. package/dist/test/suites/build/defaults-scaffold.test.js +21 -7
  153. package/dist/test/suites/build/deploy-direct.test.js +7 -5
  154. package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
  155. package/dist/test/suites/build/deploy-hook.test.js +7 -5
  156. package/dist/test/suites/build/dev-verb.test.js +67 -0
  157. package/dist/test/suites/build/ensure-target.test.js +13 -5
  158. package/dist/test/suites/build/env-delivery.test.js +2 -2
  159. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  160. package/dist/test/suites/build/exports.test.js +9 -8
  161. package/dist/test/suites/build/get-config.test.js +4 -4
  162. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  163. package/dist/test/suites/build/merge-line-files.test.js +7 -7
  164. package/dist/test/suites/build/migrate.test.js +29 -0
  165. package/dist/test/suites/build/omega-shell.test.js +34 -2
  166. package/dist/test/suites/build/omega.test.js +350 -0
  167. package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
  168. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  169. package/dist/test/suites/build/runner-env-write.test.js +73 -0
  170. package/dist/test/suites/build/runner.test.js +11 -10
  171. package/dist/test/suites/build/sentry.test.js +2 -2
  172. package/dist/test/suites/build/setup-scripts.test.js +27 -0
  173. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  174. package/dist/test/suites/build/templating.test.js +3 -3
  175. package/dist/test/suites/build/test-stealth.test.js +7 -9
  176. package/dist/test/suites/build/url-helpers.test.js +55 -56
  177. package/dist/test/suites/build/validate-config.test.js +15 -4
  178. package/dist/test/suites/build/verb-logs.test.js +20 -0
  179. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  180. package/dist/test/suites/main/analytics.test.js +59 -59
  181. package/dist/test/suites/main/app-state.test.js +66 -66
  182. package/dist/test/suites/main/auth-flow.test.js +41 -41
  183. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  184. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  185. package/dist/test/suites/main/auth.test.js +336 -0
  186. package/dist/test/suites/main/auto-updater.test.js +134 -134
  187. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  188. package/dist/test/suites/main/context-menu.test.js +51 -50
  189. package/dist/test/suites/main/context.test.js +25 -25
  190. package/dist/test/suites/main/deep-link.test.js +74 -74
  191. package/dist/test/suites/main/fontawesome.test.js +27 -27
  192. package/dist/test/suites/main/ipc.test.js +35 -35
  193. package/dist/test/suites/main/menu.test.js +101 -100
  194. package/dist/test/suites/main/protocol.test.js +19 -19
  195. package/dist/test/suites/main/remote-config.test.js +63 -63
  196. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  197. package/dist/test/suites/main/request.test.js +71 -0
  198. package/dist/test/suites/main/restart-manager.test.js +33 -33
  199. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  200. package/dist/test/suites/main/startup.test.js +26 -26
  201. package/dist/test/suites/main/stealth-window.test.js +1 -1
  202. package/dist/test/suites/main/storage.test.js +25 -25
  203. package/dist/test/suites/main/theme.test.js +34 -34
  204. package/dist/test/suites/main/tray.test.js +79 -79
  205. package/dist/test/suites/main/url-helpers.test.js +133 -133
  206. package/dist/test/suites/main/usage.test.js +25 -25
  207. package/dist/test/suites/main/window-bounds.test.js +27 -27
  208. package/dist/test/suites/main/window-manager.test.js +44 -44
  209. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  210. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  211. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  212. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  213. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +28 -8
  214. package/dist/test/utils/extended-mode-warning.js +1 -1
  215. package/dist/utils/boot-harness.js +56 -0
  216. package/dist/utils/build-pipeline.js +4 -4
  217. package/dist/utils/mode-helpers.js +2 -15
  218. package/dist/utils/runner-env.js +13 -28
  219. package/dist/utils/ship-keys.js +3 -3
  220. package/dist/utils/signing-status.js +51 -0
  221. package/dist/utils/test-events.js +7 -0
  222. package/dist/utils/test-stealth.js +6 -6
  223. package/dist/utils/url-helpers.js +52 -42
  224. package/dist/utils/user-agent.js +44 -0
  225. package/dist/vendor/account/engine.js +3 -3
  226. package/dist/vendor/account/index.js +14 -45
  227. package/dist/vendor/account/resolve-account.js +44 -0
  228. package/dist/vendor/account/schema.js +1 -1
  229. package/dist/vendor/account/user.js +99 -0
  230. package/dist/vendor/config/client-config.js +1 -1
  231. package/dist/vendor/config/company.js +46 -14
  232. package/dist/vendor/config/defaults.js +30 -7
  233. package/dist/vendor/config/edit.js +25 -3
  234. package/dist/vendor/config/env-delivery.js +1 -1
  235. package/dist/vendor/config/env-schema.js +3 -6
  236. package/dist/vendor/config/env.js +34 -22
  237. package/dist/vendor/config/environment.js +11 -30
  238. package/dist/vendor/config/index.js +21 -28
  239. package/dist/vendor/config/load.js +16 -9
  240. package/dist/vendor/config/platforms.js +1 -1
  241. package/dist/vendor/config/repo.js +10 -27
  242. package/dist/vendor/config/schema-client.js +64 -0
  243. package/dist/vendor/config/schema-cloud.js +38 -0
  244. package/dist/vendor/config/schema-manager.js +118 -0
  245. package/dist/vendor/config/schema-overrides.js +68 -0
  246. package/dist/vendor/config/schema.js +104 -160
  247. package/dist/vendor/config/site-global.js +2 -3
  248. package/dist/vendor/config/validate.js +97 -78
  249. package/dist/vendor/config/winback.js +1 -1
  250. package/dist/vendor/devkit/actions-secrets.js +1 -1
  251. package/dist/vendor/devkit/agents-md.js +233 -0
  252. package/dist/vendor/devkit/attach-log-file.js +16 -2
  253. package/dist/vendor/devkit/build-json.js +1 -1
  254. package/dist/vendor/devkit/ci-workflows.js +30 -30
  255. package/dist/vendor/devkit/cli-router.js +16 -11
  256. package/dist/vendor/devkit/defaults-engine.js +15 -51
  257. package/dist/vendor/devkit/deploy-snapshot.js +44 -9
  258. package/dist/vendor/devkit/env-lines.js +183 -0
  259. package/dist/vendor/devkit/local.js +64 -10
  260. package/dist/vendor/devkit/lockfile.js +32 -13
  261. package/dist/vendor/devkit/logger.js +7 -2
  262. package/dist/vendor/devkit/merge-line-files.js +219 -177
  263. package/dist/vendor/devkit/omega-bin.js +208 -111
  264. package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
  265. package/dist/vendor/devkit/preludes/index.js +1 -0
  266. package/dist/vendor/devkit/target-picker.js +45 -0
  267. package/dist/vendor/devkit/test/dashed-files.js +37 -0
  268. package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
  269. package/dist/vendor/devkit/test/runner-core.js +6 -6
  270. package/dist/vendor/devkit/update.js +15 -15
  271. package/dist/vendor/devkit/verb-scripts.js +40 -0
  272. package/dist/vendor/devkit/verbs.js +170 -0
  273. package/dist/vendor/monitoring/env.js +2 -2
  274. package/dist/vendor/monitoring/index.js +1 -1
  275. package/dist/vendor/monitoring/main.js +1 -1
  276. package/dist/vendor/monitoring/preload.js +1 -1
  277. package/dist/vendor/monitoring/renderer.js +1 -1
  278. package/package.json +19 -26
  279. package/dist/commands/install.js +0 -37
  280. package/dist/defaults/AGENTS.md +0 -110
  281. package/dist/defaults/CLAUDE.md +0 -1
  282. package/dist/lib/client-bridge.js +0 -374
  283. package/dist/lib/logger.js +0 -4
  284. package/dist/test/suites/build/manager.test.js +0 -213
  285. package/dist/test/suites/main/client-bridge.test.js +0 -262
  286. package/dist/vendor/config/env-retired.js +0 -137
  287. package/dist/vendor/config/retired-keys.js +0 -635
  288. package/docs/analytics.md +0 -140
  289. package/docs/app-state.md +0 -92
  290. package/docs/audit.md +0 -69
  291. package/docs/auto-updater.md +0 -243
  292. package/docs/boot-sequence.md +0 -39
  293. package/docs/build-system.md +0 -169
  294. package/docs/cdp-debugging.md +0 -169
  295. package/docs/client-bridge.md +0 -269
  296. package/docs/common-mistakes.md +0 -21
  297. package/docs/config-schema.md +0 -120
  298. package/docs/context-menu.md +0 -112
  299. package/docs/context.md +0 -81
  300. package/docs/css.md +0 -90
  301. package/docs/deep-link.md +0 -186
  302. package/docs/environment-detection.md +0 -112
  303. package/docs/fontawesome.md +0 -107
  304. package/docs/hooks.md +0 -89
  305. package/docs/icons.md +0 -79
  306. package/docs/index.md +0 -317
  307. package/docs/installer-options.md +0 -165
  308. package/docs/ipc.md +0 -61
  309. package/docs/lib-modules.md +0 -53
  310. package/docs/logging.md +0 -229
  311. package/docs/menu.md +0 -160
  312. package/docs/releasing.md +0 -239
  313. package/docs/remote-config.md +0 -118
  314. package/docs/remote-scripts.md +0 -144
  315. package/docs/restart-manager.md +0 -144
  316. package/docs/runner.md +0 -290
  317. package/docs/sentry.md +0 -97
  318. package/docs/shared/agent-docs.md +0 -89
  319. package/docs/shared/analytics.md +0 -612
  320. package/docs/shared/brands.md +0 -57
  321. package/docs/shared/breaking-changes.md +0 -851
  322. package/docs/shared/config.md +0 -1952
  323. package/docs/shared/deploys.md +0 -341
  324. package/docs/shared/icons.md +0 -219
  325. package/docs/shared/local-dev.md +0 -167
  326. package/docs/shared/logging.md +0 -205
  327. package/docs/shared/monitoring.md +0 -167
  328. package/docs/shared/publishing.md +0 -187
  329. package/docs/shared/rulings.md +0 -34
  330. package/docs/shared/testing.md +0 -147
  331. package/docs/shared/theming.md +0 -629
  332. package/docs/shared/translation.md +0 -333
  333. package/docs/shared/updates.md +0 -61
  334. package/docs/signing.md +0 -293
  335. package/docs/startup.md +0 -142
  336. package/docs/storage.md +0 -59
  337. package/docs/templating.md +0 -101
  338. package/docs/test-boot-layer.md +0 -157
  339. package/docs/test-framework.md +0 -362
  340. package/docs/themes.md +0 -149
  341. package/docs/tooltips.md +0 -99
  342. package/docs/tray.md +0 -164
  343. package/docs/usage.md +0 -58
  344. package/docs/verts.md +0 -62
  345. package/docs/windows.md +0 -149
@@ -1,8 +1,8 @@
1
- // Boot-layer self-test — @omega.js/desktop's analog of "does the extension load?" (BXM) / "does the
2
- // site boot?" (UJM). The boot runner esbuild-builds the bundled fixture consumer
1
+ // Boot-layer self-test — @omega.js/desktop's analog of "does the extension load?" /
2
+ // "does the site boot?". The boot runner esbuild-builds the bundled fixture consumer
3
3
  // (src/test/fixtures/consumer-app) into a real main.bundle.js, spawns Electron with
4
4
  // it (the actual production boot path — bundled, not the unbundled lib code that the
5
- // `main` layer exercises), then runs these inspects against the live manager.
5
+ // `main` layer exercises), then runs these inspects against the live omega instance.
6
6
  //
7
7
  // In @omega.js/desktop's own test run, OMEGA_TEST_BOOT_PROJECT points at the fixture (auto-set in
8
8
  // src/commands/test.js when the cwd is the @omega.js/desktop repo). In a real consumer's
@@ -11,7 +11,7 @@
11
11
  // boot tests under <cwd>/test/boot/.
12
12
  //
13
13
  // NOTE: inspect bodies are serialized to the spawned Electron process — no closures over
14
- // module scope. `require`, `process`, and `Buffer` are injected; { manager, expect,
14
+ // module scope. `require`, `process`, and `Buffer` are injected; { omega, expect,
15
15
  // projectRoot, appRoot, frameworkDistRoot, distSnapshotBefore } is the inspect argument
16
16
  // (projectRoot = the fixture root; appRoot = the staged target root holding the build).
17
17
 
@@ -24,25 +24,25 @@ module.exports = defineCases({
24
24
  timeout: 30000,
25
25
  tests: [
26
26
  {
27
- description: 'manager initialized with all core libs wired',
28
- inspect: async ({ manager, expect }) => {
29
- expect(manager).toBeTruthy();
30
- expect(manager._initialized).toBe(true);
31
- for (const lib of ['storage', 'ipc', 'windows', 'tray', 'menu', 'contextMenu', 'omega']) {
32
- expect(Boolean(manager[lib])).toBe(true);
27
+ description: 'omega initialized with all core libs wired',
28
+ inspect: async ({ omega, expect }) => {
29
+ expect(omega).toBeTruthy();
30
+ expect(omega._initialized).toBe(true);
31
+ for (const lib of ['storage', 'ipc', 'windows', 'tray', 'menu', 'contextMenu', 'auth']) {
32
+ expect(Boolean(omega[lib])).toBe(true);
33
33
  }
34
34
  },
35
35
  },
36
36
 
37
37
  {
38
38
  description: 'the fixture main.js created the main window and loaded the built view',
39
- inspect: async ({ manager, expect }) => {
39
+ inspect: async ({ omega, expect }) => {
40
40
  const { BrowserWindow } = require('electron');
41
41
 
42
42
  // windows.create() runs inside the consumer's initialize().then(); poll for it.
43
43
  let url = '';
44
44
  for (let i = 0; i < 40; i++) {
45
- const win = manager.windows.get('main') || BrowserWindow.getAllWindows()[0];
45
+ const win = omega.windows.get('main') || BrowserWindow.getAllWindows()[0];
46
46
  if (win && !win.isDestroyed()) {
47
47
  url = win.webContents.getURL();
48
48
  if (url.includes('/views/main/')) break;
@@ -50,23 +50,23 @@ module.exports = defineCases({
50
50
  await new Promise((resolve) => setTimeout(resolve, 100));
51
51
  }
52
52
 
53
- expect(Boolean(manager.windows.get('main'))).toBe(true);
53
+ expect(Boolean(omega.windows.get('main'))).toBe(true);
54
54
  expect(url.includes('/views/main/')).toBe(true);
55
55
  },
56
56
  },
57
57
 
58
58
  {
59
59
  description: 'test stealth: app activation suppressed — dock hidden (macOS)',
60
- inspect: async ({ manager, expect }) => {
60
+ inspect: async ({ omega, expect }) => {
61
61
  if (process.platform !== 'darwin') {
62
62
  return; // accessory activation policy / dock is macOS-only
63
63
  }
64
- // Manager.initialize step 1a hides the dock under the stealth predicate,
64
+ // omega.initialize step 1a hides the dock under the stealth predicate,
65
65
  // so the spawned consumer app never activates and never steals keyboard
66
66
  // focus from the developer's editor.
67
67
  const { app } = require('electron');
68
68
  expect(app.dock.isVisible()).toBe(false);
69
- expect(manager.isTesting()).toBe(true);
69
+ expect(omega.isTesting()).toBe(true);
70
70
  },
71
71
  },
72
72
 
@@ -83,8 +83,8 @@ module.exports = defineCases({
83
83
  {
84
84
  // #111 — the fixture's renderer entry imports the vendored app-shell
85
85
  // module through the `__main_assets__` alias. Its declarative contract
86
- // showing up in the built bundle proves the whole chain: esbuild alias →
87
- // @omega.js/desktop's vendored dist asset → its @omega.js/client import.
86
+ // showing up in the built bundle proves the chain: esbuild alias →
87
+ // @omega.js/desktop's vendored dist asset.
88
88
  description: 'renderer bundle carries the vendored app-shell module via __main_assets__',
89
89
  inspect: async ({ expect, appRoot }) => {
90
90
  const fs = require('fs');
@@ -105,12 +105,12 @@ module.exports = defineCases({
105
105
  // line the bridge logs next is out of reach here, because the fixture's
106
106
  // `cloud.config` is empty and this boot never initializes Firebase auth.)
107
107
  description: 'the booted app runs in the lane environment, not the one baked into its bundle (#925)',
108
- inspect: async ({ manager, expect, projectRoot }) => {
108
+ inspect: async ({ omega, expect, projectRoot }) => {
109
109
  const fs = require('fs');
110
110
  const path = require('path');
111
111
 
112
- expect(manager.isTesting()).toBe(true);
113
- expect(manager.config.environment).toBe('production'); // the artifact IS a production build
112
+ expect(omega.isTesting()).toBe(true);
113
+ expect(omega.config.environment).toBe('production'); // the artifact IS a production build
114
114
 
115
115
  const log = fs.readFileSync(path.join(projectRoot, 'logs', 'runtime.log'), 'utf8');
116
116
  expect(log.includes('auth persistence: none (test mode)')).toBe(true);
@@ -118,11 +118,11 @@ module.exports = defineCases({
118
118
  },
119
119
 
120
120
  {
121
- // #925: a page has no `process`, so its Manager reads the baked word. The
121
+ // #925: a page has no `process`, so its instance reads the baked word. The
122
122
  // preload hands the running one over on `window.desktop`, and the renderer
123
123
  // bootstrap applies it, so this window answers what main answers.
124
124
  description: 'the main window renderer answers the lane environment too (#925)',
125
- inspect: async ({ manager, expect }) => {
125
+ inspect: async ({ omega, expect }) => {
126
126
  const { BrowserWindow } = require('electron');
127
127
 
128
128
  // The window is created in the consumer's initialize().then(), and its
@@ -131,10 +131,10 @@ module.exports = defineCases({
131
131
  let answer = null;
132
132
  let win = null;
133
133
  for (let i = 0; i < 40; i++) {
134
- win = manager.windows.get('main') || BrowserWindow.getAllWindows()[0];
134
+ win = omega.windows.get('main') || BrowserWindow.getAllWindows()[0];
135
135
  if (win && !win.isDestroyed() && !win.webContents.isLoading()) {
136
136
  answer = await win.webContents.executeJavaScript(
137
- 'window.__omegaManager && window.__omegaManager.config ? window.__omegaManager.getEnvironment() : null',
137
+ 'window.__omegaInstance && window.__omegaInstance.config.environment ? window.__omegaInstance.getEnvironment() : null',
138
138
  );
139
139
  if (answer) break;
140
140
  }
@@ -146,7 +146,38 @@ module.exports = defineCases({
146
146
 
147
147
  expect(baked).toBe('production'); // what the build baked
148
148
  expect(bridged).toBe('testing'); // what the preload read off the lane
149
- expect(answer).toBe('testing'); // what the renderer's Manager answers
149
+ expect(answer).toBe('testing'); // what the renderer's instance answers
150
+ },
151
+ },
152
+
153
+ {
154
+ // The renderer builds `omega.shell` from ITSELF with the vendored app
155
+ // shell's createShell(omega), exactly as web builds it; the fixture binds
156
+ // the same export through the `__main_assets__` alias (#111).
157
+ description: 'the main window renderer carries omega.shell, built by createShell(omega)',
158
+ inspect: async ({ omega, expect }) => {
159
+ const { BrowserWindow } = require('electron');
160
+
161
+ let probe = null;
162
+ for (let i = 0; i < 40; i++) {
163
+ const win = omega.windows.get('main') || BrowserWindow.getAllWindows()[0];
164
+ if (win && !win.isDestroyed() && !win.webContents.isLoading()) {
165
+ probe = await win.webContents.executeJavaScript(`(() => {
166
+ const instance = window.__omegaInstance;
167
+ if (!instance || !instance.shell) return null;
168
+ return {
169
+ createShell: typeof window.__omegaCreateShell,
170
+ isCollapsed: typeof instance.shell.isCollapsed,
171
+ toggleOpen: typeof instance.shell.toggleOpen,
172
+ desktopIsBridge: instance.desktop === window.desktop,
173
+ };
174
+ })()`);
175
+ if (probe) break;
176
+ }
177
+ await new Promise((resolve) => setTimeout(resolve, 100));
178
+ }
179
+
180
+ expect(probe).toEqual({ createShell: 'function', isCollapsed: 'function', toggleOpen: 'function', desktopIsBridge: true });
150
181
  },
151
182
  },
152
183
  ],
@@ -16,8 +16,8 @@ module.exports = defineCases({
16
16
  tests: [
17
17
  {
18
18
  description: 'restartManager wired, bailed as testing, nothing scheduled',
19
- inspect: async ({ manager, expect }) => {
20
- const rm = manager.restartManager;
19
+ inspect: async ({ omega, expect }) => {
20
+ const rm = omega.restartManager;
21
21
  expect(Boolean(rm)).toBe(true);
22
22
  for (const fn of ['register', 'unregister', 'ensureInstalled', 'ensureRunning', 'getStatus', 'shutdown']) {
23
23
  expect(typeof rm[fn]).toBe('function');
@@ -40,19 +40,19 @@ module.exports = defineCases({
40
40
 
41
41
  {
42
42
  description: 'storage is a REAL store through the bundle (not the no-op fallback)',
43
- inspect: async ({ manager, expect }) => {
43
+ inspect: async ({ omega, expect }) => {
44
44
  const fs = require('fs');
45
45
 
46
46
  // The no-op fallback leaves _store null → getPath() null and get() always default.
47
- manager.storage.set('desktop:boot:storageProof', 'bundled');
48
- expect(manager.storage.get('desktop:boot:storageProof')).toBe('bundled');
47
+ omega.storage.set('desktop:boot:storageProof', 'bundled');
48
+ expect(omega.storage.get('desktop:boot:storageProof')).toBe('bundled');
49
49
 
50
- const storePath = manager.storage.getPath();
50
+ const storePath = omega.storage.getPath();
51
51
  expect(Boolean(storePath)).toBe(true);
52
52
  expect(storePath.endsWith('omega-storage.json')).toBe(true);
53
53
  expect(fs.existsSync(storePath)).toBe(true);
54
54
 
55
- manager.storage.delete('desktop:boot:storageProof');
55
+ omega.storage.delete('desktop:boot:storageProof');
56
56
  },
57
57
  },
58
58
  ],
@@ -16,39 +16,39 @@ module.exports = defineCases({
16
16
  tests: [
17
17
  {
18
18
  description: 'page boots with data-bs-theme equal to the resolved appearance',
19
- inspect: async ({ manager, expect }) => {
19
+ inspect: async ({ omega, expect }) => {
20
20
  const { BrowserWindow } = require('electron');
21
21
 
22
- expect(manager.theme._initialized).toBe(true);
23
- expect(['light', 'dark'].includes(manager.theme.resolved())).toBe(true);
22
+ expect(omega.theme._initialized).toBe(true);
23
+ expect(['light', 'dark'].includes(omega.theme.resolved())).toBe(true);
24
24
 
25
25
  // Wait for the fixture's main window + view, then for the applier to land
26
26
  // (it applies at DOMContentLoaded).
27
27
  let attr = null;
28
28
  for (let i = 0; i < 50; i++) {
29
- const win = manager.windows.get('main') || BrowserWindow.getAllWindows()[0];
29
+ const win = omega.windows.get('main') || BrowserWindow.getAllWindows()[0];
30
30
  if (win && !win.isDestroyed() && win.webContents.getURL().includes('/views/main/')) {
31
31
  attr = await win.webContents.executeJavaScript('document.documentElement.getAttribute("data-bs-theme")').catch(() => null);
32
- if (attr === manager.theme.resolved()) break;
32
+ if (attr === omega.theme.resolved()) break;
33
33
  }
34
34
  await new Promise((resolve) => setTimeout(resolve, 100));
35
35
  }
36
36
 
37
- expect(attr).toBe(manager.theme.resolved());
37
+ expect(attr).toBe(omega.theme.resolved());
38
38
  },
39
39
  },
40
40
 
41
41
  {
42
42
  description: 'main-side theme.set() updates the live page attribute (no reload)',
43
- inspect: async ({ manager, expect }) => {
43
+ inspect: async ({ omega, expect }) => {
44
44
  const { BrowserWindow } = require('electron');
45
- const win = manager.windows.get('main') || BrowserWindow.getAllWindows()[0];
45
+ const win = omega.windows.get('main') || BrowserWindow.getAllWindows()[0];
46
46
  expect(Boolean(win && !win.isDestroyed())).toBe(true);
47
47
 
48
- const original = manager.theme.get();
49
- const target = manager.theme.resolved() === 'dark' ? 'light' : 'dark';
48
+ const original = omega.theme.get();
49
+ const target = omega.theme.resolved() === 'dark' ? 'light' : 'dark';
50
50
 
51
- manager.theme.set(target);
51
+ omega.theme.set(target);
52
52
 
53
53
  let attr = null;
54
54
  for (let i = 0; i < 50; i++) {
@@ -58,8 +58,8 @@ module.exports = defineCases({
58
58
  }
59
59
 
60
60
  // Restore before asserting so a failure can't strand the flipped state.
61
- manager.theme.set(original);
62
- manager.storage.delete('theme.appearance');
61
+ omega.theme.set(original);
62
+ omega.storage.delete('theme.appearance');
63
63
 
64
64
  expect(attr).toBe(target);
65
65
  },
@@ -12,7 +12,7 @@ const defineCases = require('../../../vendor/devkit/test/define-cases.js');
12
12
  const auditPath = path.join(__dirname, '..', '..', '..', 'gulp', 'tasks', 'audit.js');
13
13
 
14
14
  function freshAudit() {
15
- // Clear require cache so each test gets a clean module (it instantiates Manager at require time).
15
+ // Clear require cache so each test gets a clean module (it loads the build module at require time).
16
16
  delete require.cache[require.resolve(auditPath)];
17
17
  return require(auditPath);
18
18
  }
@@ -103,18 +103,31 @@ module.exports = defineCases({
103
103
  },
104
104
  },
105
105
  {
106
- // #911: the task took only `errors` off validateConfig, so a consumer
107
- // read `audit ok (0 warnings)` while the validator's list named real
108
- // findings (a key the schema does not declare, which is what a typo
109
- // looks like). The report is both lists now.
110
- name: 'prints the validator\'s warnings and counts them (#911)',
106
+ // The schema is strict: a key nothing declares is what a typo (or a
107
+ // legacy shape) looks like, and it fails the build naming the fix.
108
+ name: 'an undeclared key fails the audit, naming omega migrate',
111
109
  run: async (ctx) => {
112
110
  const tmp = stageConsumer({ brand: { id: 'testapp', name: 'TestApp' } }, { notAKey: true });
111
+ try {
112
+ const err = await runAudit(tmp);
113
+ ctx.expect(err).toBeDefined();
114
+ ctx.expect(err.message).toMatch(/config\.notAKey is not a key the schema declares/);
115
+ ctx.expect(err.message).toMatch(/npx omega migrate/);
116
+ } finally {
117
+ fs.rmSync(tmp, { recursive: true, force: true });
118
+ }
119
+ },
120
+ },
121
+ {
122
+ // The resolved config carries the company the loader fills and the
123
+ // environment the build attaches: neither is the brand's key.
124
+ name: 'a clean config passes with the loader-filled and build-attached keys on it',
125
+ run: async (ctx) => {
126
+ const tmp = stageConsumer({ brand: { id: 'testapp', name: 'TestApp' } }, { electronBuilder: { mac: { hardenedRuntime: true } } });
113
127
  try {
114
128
  const { err, output } = await runAuditCapturing(tmp);
115
129
  ctx.expect(err).toBeNull();
116
- ctx.expect(output).toMatch(/notAKey/);
117
- ctx.expect(output).toMatch(/audit ok \(1 warning\)/);
130
+ ctx.expect(output).toMatch(/audit ok \(0 warnings\)/);
118
131
  } finally {
119
132
  fs.rmSync(tmp, { recursive: true, force: true });
120
133
  }
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // The managers are plain objects and `available()` is stubbed, so the production
5
5
  // default is provable with no Electron and, above all, with no call into this box's
6
- // OS keychain. The real-manager half lives in the main suite, which now runs under
6
+ // OS keychain. The real-instance half lives in the main suite, which now runs under
7
7
  // the forced test-mode strategy itself.
8
8
 
9
9
  const path = require('path');
@@ -41,7 +41,7 @@ module.exports = defineCases({
41
41
  description: 'auth-persistence resolve(): the production default, and the test-mode override',
42
42
  tests: [
43
43
  {
44
- name: 'a production manager with no config still picks safeStorage; an unknown name warns to null',
44
+ name: 'a production omega instance with no config still picks safeStorage; an unknown name warns to null',
45
45
  run: async (ctx) => {
46
46
  const vault = stubSafeStorage();
47
47
  const lines = [];
@@ -63,7 +63,7 @@ module.exports = defineCases({
63
63
  },
64
64
  },
65
65
  {
66
- name: 'a testing manager gets none before any config read, and the vault is never asked',
66
+ name: 'a testing omega instance gets none before any config read, and the vault is never asked',
67
67
  run: async (ctx) => {
68
68
  const vault = stubSafeStorage();
69
69
  const lines = [];
@@ -97,13 +97,13 @@ module.exports = defineCases({
97
97
  // explicit one alone ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)),
98
98
  // and so the real isTesting() answers the lane, not the bake.
99
99
  process.env[ENVIRONMENT_VAR] = 'testing';
100
- const manager = {
100
+ const omega = {
101
101
  config: { environment: 'production', omega: { authPersistence: 'safeStorage' } },
102
102
  isTesting,
103
103
  };
104
- ctx.expect(manager.isTesting()).toBe(true);
104
+ ctx.expect(omega.isTesting()).toBe(true);
105
105
 
106
- const active = await capture(lines, () => authPersistence.resolve(manager));
106
+ const active = await capture(lines, () => authPersistence.resolve(omega));
107
107
  ctx.expect(active).toBeNull();
108
108
  ctx.expect(vault.calls.available).toBe(0);
109
109
  ctx.expect(lines.join('\n')).toMatch(/auth persistence: none \(test mode\)/);
@@ -15,9 +15,9 @@
15
15
 
16
16
  const path = require('path');
17
17
 
18
- const Manager = require('../../../build.js');
18
+ const build = require('../../../build.js');
19
19
 
20
- const package = Manager.getPackage('main');
20
+ const package = build.getPackage('main');
21
21
  const fixture = require(path.join(__dirname, '..', '..', 'fixtures', 'consumer-app', 'package.json'));
22
22
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
23
23
 
@@ -15,6 +15,7 @@ const jetpack = require('fs-jetpack');
15
15
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
16
16
 
17
17
  const { runBootChild } = require(path.join(__dirname, '..', '..', 'runners', 'boot.js'));
18
+ const { TEST_EVENT_PREFIX } = require(path.join(__dirname, '..', '..', '..', 'utils', 'test-events.js'));
18
19
 
19
20
  // A project root the runner reads its report clue from. `logLine` null writes no
20
21
  // logs/ at all, the boot that died before the logger ever opened a file.
@@ -152,11 +153,11 @@ module.exports = defineCases({
152
153
  killGraceMs: 20,
153
154
  });
154
155
 
155
- child.stdout.emit('data', `__EM_TEST__${JSON.stringify({ event: 'result', name: 'the app boots', passed: true, duration: 12 })}\n`);
156
+ child.stdout.emit('data', `${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'result', name: 'the app boots', passed: true, duration: 12 })}\n`);
156
157
  await sleep(150);
157
- child.stdout.emit('data', `__EM_TEST__${JSON.stringify({ event: 'result', name: 'a slow suite finishes', passed: true, duration: 12 })}\n`);
158
+ child.stdout.emit('data', `${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'result', name: 'a slow suite finishes', passed: true, duration: 12 })}\n`);
158
159
  await sleep(150);
159
- child.stdout.emit('data', `__EM_TEST__${JSON.stringify({ event: 'result', name: 'and another', passed: true, duration: 12 })}\n`);
160
+ child.stdout.emit('data', `${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'result', name: 'and another', passed: true, duration: 12 })}\n`);
160
161
  await sleep(150);
161
162
  child.emit('exit', 0);
162
163
 
@@ -196,7 +197,7 @@ module.exports = defineCases({
196
197
  killGraceMs: 20,
197
198
  });
198
199
 
199
- child.stdout.emit('data', `__EM_TEST__${JSON.stringify({ event: 'result', name: 'a late line', passed: true, duration: 12 })}\n`);
200
+ child.stdout.emit('data', `${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'result', name: 'a late line', passed: true, duration: 12 })}\n`);
200
201
  child.emit('exit', 0);
201
202
  await sleep(40);
202
203
 
@@ -231,7 +232,7 @@ module.exports = defineCases({
231
232
  killGraceMs: 20,
232
233
  });
233
234
 
234
- child.stdout.emit('data', `__EM_TEST__${JSON.stringify({ event: 'result', name: 'the app boots', passed: true, duration: 12 })}\n`);
235
+ child.stdout.emit('data', `${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'result', name: 'the app boots', passed: true, duration: 12 })}\n`);
235
236
  child.emit('exit', 0);
236
237
 
237
238
  const settled = await pending;
@@ -29,7 +29,7 @@ function stageConsumer(color) {
29
29
 
30
30
  /**
31
31
  * Run the sass task with the fixture as the project root. Both the task and the
32
- * build Manager resolve that root at REQUIRE time, so each run gets a fresh
32
+ * build module resolve that root at REQUIRE time, so each run gets a fresh
33
33
  * copy of both.
34
34
  */
35
35
  function runSassIn(dir) {
@@ -133,7 +133,7 @@ module.exports = defineCases({
133
133
  ctx.expect(blob.license.status).toBe('licensed');
134
134
  ctx.expect(typeof blob.builtAt).toBe('string');
135
135
  // The mode is the same THREE keys everywhere (#894): desktop's own
136
- // `server` verdict stays inside the Manager.
136
+ // `server` verdict stays inside the build module.
137
137
  ctx.expect(Object.keys(blob.mode).sort()).toEqual(['build', 'environment', 'publish']);
138
138
  ctx.expect(blob.mode.environment).toBe('production');
139
139
  ctx.expect(blob.mode.build).toBe(true);
@@ -122,8 +122,8 @@ module.exports = defineCases({
122
122
  ctx.expect(decode.run).toContain('if [ -n "${{ secrets.CSC_LINK }}" ]; then');
123
123
  ctx.expect(decode.run).toContain('if [ -n "${{ secrets.APPLE_API_KEY }}" ]; then');
124
124
  // The standalone verb is gone (#891): the deploy precheck pushes them.
125
- ctx.expect(decode.run).toContain('No CSC_LINK secret: run omega deploy from targets/desktop');
126
- ctx.expect(decode.run).toContain('No APPLE_API_KEY secret: run omega deploy from targets/desktop');
125
+ ctx.expect(decode.run).toContain('No CSC_LINK secret: run omega deploy at the brand root');
126
+ ctx.expect(decode.run).toContain('No APPLE_API_KEY secret: run omega deploy at the brand root');
127
127
  ctx.expect(decode.run).not.toContain('push-secrets');
128
128
  ctx.expect(decode.run.match(/exit 1/g).length).toBe(2);
129
129
  ctx.expect(decode.run).not.toContain('this build will not be signed');
@@ -3,9 +3,9 @@
3
3
  const path = require('path');
4
4
  const fs = require('fs');
5
5
 
6
- const Manager = require('../../../build.js');
6
+ const build = require('../../../build.js');
7
7
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
8
- const root = Manager.getRootPath('main');
8
+ const root = build.getRootPath('main');
9
9
 
10
10
  module.exports = defineCases({
11
11
  type: 'group',
@@ -145,6 +145,34 @@ module.exports = defineCases({
145
145
  }
146
146
  },
147
147
  },
148
+ {
149
+ name: 'update: --dry-run reaches devkit runUpdate as dryRun, and a bare run installs',
150
+ run: async (ctx) => {
151
+ const devkitUpdate = require('../../../vendor/devkit/update.js');
152
+ const { BOOLEAN_FLAGS } = require(path.join(root, 'dist', 'cli-run.js'));
153
+ const { parseArgv } = require('../../../vendor/devkit/argv.js');
154
+ const commandFile = path.join(root, 'dist', 'commands', 'update.js');
155
+
156
+ // The command destructures runUpdate at load, so the stub lands before a fresh require
157
+ async function run(args) {
158
+ const original = devkitUpdate.runUpdate;
159
+ const seen = [];
160
+ devkitUpdate.runUpdate = async (options) => { seen.push(options); };
161
+ delete require.cache[commandFile];
162
+ try {
163
+ await require(commandFile)(parseArgv(args, { booleans: BOOLEAN_FLAGS }));
164
+ } finally {
165
+ devkitUpdate.runUpdate = original;
166
+ delete require.cache[commandFile];
167
+ }
168
+ ctx.expect(seen.length).toBe(1);
169
+ return seen[0];
170
+ }
171
+
172
+ ctx.expect((await run(['update', '--dry-run'])).dryRun).toBe(true);
173
+ ctx.expect(Boolean((await run(['update'])).dryRun)).toBe(false);
174
+ },
175
+ },
148
176
  {
149
177
  name: 'mirrored aliases: -t routes to test, -d routes to deploy (wave-6 D6)',
150
178
  run: (ctx) => {
@@ -10,9 +10,9 @@ const fs = require('fs');
10
10
  const JSON5 = require('json5');
11
11
  const { loadConfig } = require('../../../vendor/config/index.js');
12
12
 
13
- const Manager = require('../../../build.js');
13
+ const build = require('../../../build.js');
14
14
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
15
- const root = Manager.getRootPath('main');
15
+ const root = build.getRootPath('main');
16
16
  const defaultsDir = path.join(root, 'dist', 'defaults');
17
17
  const defaultConfigPath = path.join(defaultsDir, 'config', 'omega.json5');
18
18
 
@@ -76,7 +76,7 @@ module.exports = defineCases({
76
76
  name: 'resolved: has app block (appId + productName may be null — derived from brand)',
77
77
  run: (ctx) => {
78
78
  // appId and productName are derived from brand.id / brand.name at config-load
79
- // time (Manager.getConfig). The raw scaffold leaves them null on purpose so the
79
+ // time (build.getConfig). The raw scaffold leaves them null on purpose so the
80
80
  // user only sets brand.{id,name} once. The `app` block itself must exist for
81
81
  // copyright + any future explicit overrides.
82
82
  ctx.expect(ctx.state.cfg.app).toBeTruthy();
@@ -96,7 +96,7 @@ module.exports = defineCases({
96
96
  run: (ctx) => {
97
97
  // Tray, menu, and context-menu use fixed conventional paths
98
98
  // (src/integrations/{tray,menu,context-menu}/index.js). Disabling is a runtime
99
- // call (manager.tray.disable() etc.), not a config flag. Config carries no entry
99
+ // call (omega.tray.disable() etc.), not a config flag. Config carries no entry
100
100
  // for these in v1 — guard against re-introducing one accidentally.
101
101
  ctx.expect(ctx.state.cfg.tray).toBeUndefined();
102
102
  ctx.expect(ctx.state.cfg.menu).toBeUndefined();
@@ -125,7 +125,7 @@ module.exports = defineCases({
125
125
  name: 'has NO deepLinks config block (scheme = brand.id, routes are runtime)',
126
126
  run: (ctx) => {
127
127
  // deep-link scheme is auto-derived from brand.id; routes register at runtime via
128
- // manager.deepLink.on(). Guard against re-introducing a config block.
128
+ // omega.deepLink.on(). Guard against re-introducing a config block.
129
129
  ctx.expect(ctx.state.cfg.deepLinks).toBeUndefined();
130
130
  },
131
131
  },
@@ -0,0 +1,22 @@
1
+ // Every defaults file is copied into a consumer's repo, whose own guard may
2
+ // refuse an em dash (U+2014) at commit time. So no defaults file carries one.
3
+
4
+ const path = require('path');
5
+ const defineCases = require('../../../vendor/devkit/test/define-cases.js');
6
+ const { dashedFiles } = require('../../../vendor/devkit/test/dashed-files.js');
7
+
8
+ const DEFAULTS = path.join(__dirname, '..', '..', '..', 'defaults');
9
+
10
+ module.exports = defineCases({
11
+ type: 'group',
12
+ layer: 'build',
13
+ description: 'defaults tree carries no em dash',
14
+ tests: [
15
+ {
16
+ name: 'no defaults file carries an em dash',
17
+ run: (ctx) => {
18
+ ctx.expect(dashedFiles(DEFAULTS)).toEqual([]);
19
+ },
20
+ },
21
+ ],
22
+ });
@@ -9,11 +9,11 @@ const fs = require('fs');
9
9
  const os = require('os');
10
10
  const jetpack = require('fs-jetpack');
11
11
 
12
- const Manager = require('../../../build.js');
12
+ const build = require('../../../build.js');
13
13
  const { renderSecretsBlock } = require('../../../vendor/config/env-delivery.js');
14
14
  const { copyDefaults } = require('../../../commands/lib/ensure-target.js');
15
15
  const defineCases = require('../../../vendor/devkit/test/define-cases.js');
16
- const package = Manager.getPackage('main');
16
+ const package = build.getPackage('main');
17
17
 
18
18
  const DEFAULT_MARKER = '# ========== Default Values ==========';
19
19
  const CUSTOM_MARKER = '# ========== Custom Values ==========';
@@ -34,10 +34,11 @@ module.exports = defineCases({
34
34
  // .env and every verb delivers them.
35
35
  ctx.expect(jetpack.exists(path.join(tmp, '.env'))).toBe(false);
36
36
  ctx.expect(jetpack.exists(path.join(tmp, '.gitignore'))).toBeTruthy();
37
- // The agent-docs chain (#63): AGENTS.md carries the content, CLAUDE.md is
38
- // the one-line `@AGENTS.md` pointer.
39
- ctx.expect(jetpack.read(path.join(tmp, 'AGENTS.md'))).toContain('node_modules/@omega.js/AGENTS.md');
40
- ctx.expect(jetpack.read(path.join(tmp, 'CLAUDE.md')).trim()).toBe('@AGENTS.md');
37
+ // A standalone project root gets the same AGENTS.md a brand root does:
38
+ // the manager import under Default, its notes under Custom. Claude Code reads
39
+ // AGENTS.md natively, so no CLAUDE.md scaffolds beside it.
40
+ ctx.expect(jetpack.read(path.join(tmp, 'AGENTS.md'))).toBe('<!-- ========== Default Values ========== -->\n@node_modules/@omega.js/manager/AGENTS.md\n\n<!-- ========== Custom Values ========== -->\n');
41
+ ctx.expect(jetpack.exists(path.join(tmp, 'CLAUDE.md'))).toBe(false);
41
42
  ctx.expect(jetpack.exists(path.join(tmp, '_mas'))).toBe(false);
42
43
  // `_`-prefixed FILENAMES are not archives — test/_init.js ships.
43
44
  ctx.expect(jetpack.exists(path.join(tmp, 'test', '_init.js'))).toBeTruthy();
@@ -213,6 +214,20 @@ module.exports = defineCases({
213
214
  ctx.expect(jetpack.exists(path.join(targetDir, 'config', 'omega.json5'))).toBe(false);
214
215
  },
215
216
  },
217
+ {
218
+ name: 'an old-template AGENTS.md converges, keeping the consumer notes under the Custom marker',
219
+ run: async (ctx) => {
220
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'desktop-defaults-'));
221
+ jetpack.write(path.join(tmp, 'AGENTS.md'),
222
+ `${DEFAULT_MARKER}\n# OMEGA Desktop consumer project\nframework guidance\n\n${CUSTOM_MARKER}\n\n## Project-specific notes\n\nAdd anything specific to THIS project here. Edits below this line are preserved across framework re-syncs.\n\nOur deploy needs the VPN up.\n`);
223
+ const warnings = [];
224
+ const applied = await copyDefaults(tmp, { log: () => {}, warn: (m) => warnings.push(m), error: () => {} });
225
+
226
+ ctx.expect(jetpack.read(path.join(tmp, 'AGENTS.md'))).toBe('<!-- ========== Default Values ========== -->\n@node_modules/@omega.js/manager/AGENTS.md\n\n<!-- ========== Custom Values ========== -->\nOur deploy needs the VPN up.\n');
227
+ ctx.expect(applied.merged.includes('AGENTS.md')).toBe(true);
228
+ ctx.expect(warnings.some((m) => m.includes('Converged AGENTS.md'))).toBe(true);
229
+ },
230
+ },
216
231
  {
217
232
  name: 'brand target scaffolds NO per-target docs (brand doc unification: the brand root is the doc home)',
218
233
  run: async (ctx) => {
@@ -240,7 +255,6 @@ module.exports = defineCases({
240
255
  // Standalone scaffold first (no brand config yet) — per-target docs land.
241
256
  await copyDefaults(targetDir);
242
257
  ctx.expect(jetpack.exists(path.join(targetDir, 'AGENTS.md'))).toBeTruthy();
243
- ctx.expect(jetpack.exists(path.join(targetDir, 'CLAUDE.md'))).toBeTruthy();
244
258
 
245
259
  // Wrap it in a brand monorepo: the next setup sweeps the untouched docs.
246
260
  jetpack.write(path.join(tmp, 'brand', 'config', 'omega.json5'), "{ brand: { id: 'acme', name: 'Acme' } }\n");