@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,333 +0,0 @@
1
- # Translation
2
-
3
- AI translation for OMEGA consumers — one engine, config-driven, with a
4
- **committed** per-string cache. Shipped cp96 (Ian directive 2026-07-11),
5
- replacing both legacy systems: UJM's OpenAI-only gulp task with the
6
- `cache-uj-translation` GitHub-branch cache, and BXM's Claude-only task with a
7
- gitignored `.cache/` (which re-translated everything on any change and on
8
- every fresh clone).
9
-
10
- ## Config (shared `translation` section of omega.json5)
11
-
12
- ```json5
13
- translation: {
14
- enabled: true, // optional master switch (default true)
15
- default: 'en', // source language (default 'en')
16
- languages: ['es', 'fr'],// target codes — EMPTY/ABSENT = translation off
17
- providers: { claude: {} },// the engine is a KEY (#425): claude | chatgpt. Absent block = claude
18
- model: null, // optional override for the chosen engine (claude → 'sonnet' alias, chatgpt → 'gpt-5.4-nano')
19
- include: ['**', '!blog/**'], // web only: globs over BRAND page routes, `!` negates; this is the framework default, a brand list replaces it (#858; the framework's own default pages are excluded on their own, #605)
20
- }
21
- ```
22
-
23
- Shared section (typically brand-level; `SHARED_SECTIONS` includes it, so
24
- every target inherits it through the merge chain). Language codes
25
- validate against the SSOT in `@omega.js/devkit/translate` (`LANGUAGE_NAMES`,
26
- ~32 codes) — an unknown code is a hard config error naming the supported set.
27
- The same SSOT carries `LANGUAGE_LOCALES` + `ogLocale(code)`, the one code →
28
- Open Graph `language_TERRITORY` map (`es` → `es_ES`).
29
-
30
- ## Providers
31
-
32
- | Provider | Rides | Credentials |
33
- |----------|-------|-------------|
34
- | `claude` (default) | the locally-installed Claude Code via `@anthropic-ai/claude-agent-sdk` | **none** — local auth |
35
- | `chatgpt` | OpenAI Responses API (native fetch) | `OPENAI_API_KEY` via the .env cascade |
36
-
37
- The claude provider runs **hermetic** sessions: `settingSources: []` (no user
38
- CLAUDE.md/hooks — they pollute mechanical output; a stop-hook reply actually
39
- leaked into a canary before this was locked down), a custom translator system
40
- prompt instead of the CLI persona, and NO `maxTurns` cap (a plain reply
41
- already counts as the final turn — `maxTurns: 1` reports `error_max_turns`
42
- even though the text arrived).
43
-
44
- **Enabling translation on web means installing the SDK (#37).** `@omega.js/web`
45
- does NOT ship `@anthropic-ai/claude-agent-sdk`: translation is opt-in and the
46
- SDK is heavy, so a web brand that turns it on installs it in the target itself
47
- (`npm install @anthropic-ai/claude-agent-sdk`); `@omega.js/extension` still
48
- declares it. The SDK is lazy-required at the first claude call, so a brand
49
- without translation never pays for it, and a brand that enabled translation
50
- without the SDK gets a hard error naming the package and that install command,
51
- never a silent skip. The `chatgpt` provider needs no SDK at all (native fetch
52
- plus `OPENAI_API_KEY`).
53
-
54
- **The manage cycle provisions it (#168).** Nobody types that install in a
55
- managed brand: the manager's workspace service reconciles it like every other
56
- brand file. A web app whose RESOLVED config translates with the `claude`
57
- provider gets `@anthropic-ai/claude-agent-sdk` written into its package.json
58
- `dependencies` (at the range `@omega.js/web` declares as its optional peer,
59
- read from the installed web package), followed by one `npm install` at the
60
- brand root. Converge-to-config, so: already declared (in `dependencies` or
61
- `devDependencies`) = zero-mutation no-op that never overwrites a
62
- consumer-chosen spec, `--dry-run` plans without writing, translation off or
63
- provider `chatgpt` leaves the target untouched, and turning translation back OFF
64
- never REMOVES the dep (uninstalling on a config flip is riskier than leaving
65
- it). Only web targets are provisioned, since backend and extension declare the
66
- SDK as a real dependency of the framework. The loud error above stays the backstop
67
- for hand-managed brands (`packages/manager/src/services/workspace/ensure/translation-sdk.js`,
68
- pinned by `packages/manager/test/workspace-translation-sdk.test.js`).
69
-
70
- ## Engine protocol (`@omega.js/devkit/translate`)
71
-
72
- `translateStrings({ strings, language, languageName, brand, extraRules, send })`
73
- → positionally-aligned translations:
74
-
75
- - **JSON array in → same-length JSON array out**, batches of 25.
76
- - **Batches fly concurrently**, `CONCURRENCY` wide (the constant at the top of
77
- `packages/devkit/src/translate/engine.js`, currently 5 —
78
- [#604](https://github.com/Omega-JS-Stack/omega/issues/604)). A batch is one
79
- model call and the model's latency dominates it, so a serial pass paid that
80
- latency once per 25 strings and one language took minutes it never needed.
81
- Results are stitched back in BATCH order, never completion order, and
82
- everything below still happens per batch, unchanged. Raise it only as far as
83
- the providers' rate limits allow.
84
- - **Duplicates are deduped before batching** ([#529](https://github.com/Omega-JS-Stack/omega/issues/529)):
85
- a page sends its title and description once per meta tag (`<title>`,
86
- `og:title`, `twitter:title`), so the same string used to ride a batch three
87
- times over — three times the AI spend, and adjacent twins are what a model
88
- merges. Each unique string is translated ONCE and the translation is fanned
89
- back to every occurrence. Occurrences key on the exact source string,
90
- whitespace included, so a batch is 25 UNIQUE strings.
91
- - The `OMEGA-TRANSLATION-CONTROL` sentinel is appended to EVERY batch and must
92
- return unchanged at its exact position — alignment proof per batch.
93
- - Validation failures (parse, length, sentinel) retry up to 2× then throw.
94
- - An ALIGNMENT failure (length or sentinel) that survives the retries splits the
95
- batch in half and re-asks each half, down to one string
96
- ([#523](https://github.com/Omega-JS-Stack/omega/issues/523)): a model that
97
- merges a pair of strings does it every time, so retrying the same array can
98
- only fail the same way — the playground's ship-the-docs page came back
99
- 25-for-26 on all six attempts, in both languages, and shipped untranslated.
100
- A single string that still will not come back whole throws, and the caller
101
- skips that page-language pair whole (never half-translated).
102
- - Original leading/trailing whitespace is re-applied to every translation.
103
- - Rules baked into the system prompt: preserve HTML/URLs/placeholders
104
- (`$1`, `{name}`, `{{ value }}`), never translate the brand name.
105
-
106
- ## The committed cache (`<app>/translations/`)
107
-
108
- `translations/{lang}/{namespace}.json` maps `sha256(source)[:12]` → translated
109
- string. Committed to git — that's the whole point:
110
-
111
- - **Incremental**: editing one source string changes one hash → exactly one
112
- re-translation. Everything else is a cache hit (zero provider calls).
113
- - **Survives clones/CI**: a warm cache builds a fully-translated site with NO
114
- AI credentials (kills the BXM parked finding where fresh clones burned live
115
- Claude calls). No AI key is delivered to CI by default
116
- ([#819](https://github.com/Omega-JS-Stack/omega/issues/819), Ian 2026-09-13):
117
- translation runs on the developer's machine and a runner reads the committed
118
- cache, which is why `OPENAI_API_KEY` is an `env` delivery on every target that
119
- names it and no workflow carries a line for it
120
- ([#905](https://github.com/Omega-JS-Stack/omega/issues/905) owns the one
121
- system, cloud translation included).
122
- - **Human-overridable**: hand-edit a translation VALUE in the cache file and
123
- it sticks for as long as the source is unchanged (the value is the
124
- translation; the key only changes when the SOURCE changes).
125
- - Maps are pruned to the current source set on save — no stale entries.
126
-
127
- `@omega.js/web` ships a second cache in exactly this shape for its OWN default
128
- pages, inside the package ([below](#framework-shipped-default-page-translations-621)).
129
-
130
- ## Web (`@omega.js/web`)
131
-
132
- `omega build` translates everything by default (Ian's #24 final call): warm
133
- strings come from the committed cache instantly, cold strings translate live
134
- through the provider — a build ships the COMPLETE translated site whenever
135
- the provider delivers, and a warm cache means zero provider calls. A provider
136
- FAILURE skips that page-language pair whole, warning loudly with the page and
137
- the language (the build still exits 0): no half-translated copy ever ships
138
- behind full language chrome.
139
- `omega build --cached-only` skips cold page-language pairs WHOLE instead (no
140
- mixed-language copies, hreflang stays honest; the warning lists them) for
141
- provider-free builds.
142
- `omega translate` still runs the live pass standalone against an existing
143
- dist/ and exits 1 on failures. `OMEGA_TRANSLATE_ONLY=<route>` limits any of
144
- these to one page (canary/debug).
145
-
146
- Per page × language: text nodes/`<title>`/meta/attribute copy translate
147
- (cache-first), then the copy lands at `dist/{lang}/...` with `<html lang dir>`
148
- (RTL-aware), canonical + `og:url` + `og:locale` localized, internal links
149
- rewritten to `/{lang}/...`, and hreflang + `og:locale:alternate` tags
150
- stitched into BOTH the copy and the original — naming only the languages
151
- actually PRODUCED for that page (a pair skipped cold or failed is never
152
- advertised, on the copies as on the originals), so hreflang never lies.
153
- `og:locale` carries Open Graph's `language_TERRITORY` form (`en_US`,
154
- `es_ES`) from the devkit language SSOT's locale map — on translated copies
155
- and on the source pages the head include renders. Cache namespace:
156
- `pages/{route}` (`pages/home` for `/`).
157
-
158
- On a site served under a base path ([#355](https://github.com/Omega-JS-Stack/omega/issues/355)),
159
- link rewriting composes **prefix, then language**: the pass reads the mount
160
- point off the `<html data-omega-path-prefix>` stamp the build wrote (so
161
- `omega translate` standalone sees it too), takes the route from underneath it,
162
- and mounts the language segment after it — `/workkit/es/pricing`, never
163
- `/es/workkit/pricing` ([#359](https://github.com/Omega-JS-Stack/omega/issues/359)).
164
- Exclusions are matched on that same underneath-the-prefix route. ABSOLUTE URLs
165
- (canonical, `og:url`, hreflang alternates, the sitemap entries) are built from
166
- `brand.url`, which for a mounted site already carries the path — nothing
167
- prefixes them twice.
168
-
169
- Never sent to the PROVIDER, and the framework owns the list
170
- ([#605](https://github.com/Omega-JS-Stack/omega/issues/605)): every one of its
171
- OWN default pages whose layout says it is plumbing rather than marketing copy —
172
- the auth flows, the `/app` shell, the account/payment/portal screens, the legal
173
- boilerplate, `404`, and the redirect stubs (`/login`, `/account`, `/cancel`, …).
174
- Those pages still get their `/{lang}/` copies — from the translations PACKAGED
175
- with `@omega.js/web`, at no cost to the brand (next section).
176
- The list is DERIVED from the packaged defaults tree
177
- (`packages/web/defaults/pages/**`, read by `src/translate/default-routes.js`),
178
- never typed out, so a default page that moves or arrives cannot drift out of it,
179
- and each excluded route guards its subtree too. On top of that: socials
180
- redirects (config `socials` keys), the `admin`/`test`/`team`/`updates` folders,
181
- every known language-code folder.
182
-
183
- **Which of the BRAND's own pages are translated is `translation.include`**
184
- ([#858](https://github.com/Omega-JS-Stack/omega/issues/858), Ian 2026-09-13,
185
- the same-name ruling): a list of route GLOBS read like a `.gitignore`, where
186
- `!` negates and the LAST pattern that matches a route decides it. A route no
187
- pattern matches is not translated, so an empty list translates nothing. A
188
- folder pattern covers the folder itself as well as its contents, so
189
- `!blog/**` takes `/blog` out along with every post under it. The framework
190
- default lives in the DEFAULTS layer of the merge chain (the schema's own
191
- `default:`, resolution-only so no brand file carries a copy of it):
192
-
193
- ```json5
194
- translation: { include: ['**', '!blog/**'] } // the default: the whole site except the blog
195
- ```
196
-
197
- A brand list **REPLACES** it outright rather than adding to it (arrays replace
198
- at every level of the merge chain), so a brand that writes `['docs/**']` gets
199
- docs and nothing else. It is for the brand's own pages only: the framework's
200
- derived exclusions above are not in its hands, and a brand that names `signin`
201
- or `account` is naming something already skipped.
202
-
203
- **A page overrides the list for itself**, under the same key name one level
204
- down: `translation: { include: true }` in its frontmatter translates a page the
205
- list left out, `false` takes one out that the list would have covered. The
206
- build stamps that answer on `<html data-omega-translate>` (the seam #355's base
207
- path already uses), because the pass runs post-build over `dist/` and
208
- `omega translate` runs with no build in reach. `include` is the only key a page
209
- may write under a bare `translation:`; anything else is a config section
210
- restated bare and fails the build.
211
-
212
- **`translation.exclude` is RETIRED** with it. There is no dual-read: a config
213
- still carrying it fails validation naming its replacement, and
214
- `omega migrate` at the brand root CONVERTS the list (`exclude: ['docs']`
215
- becomes `include: ['**', '!docs']`, which keeps translating exactly what the
216
- brand was translating before) and deletes the old key in the same run.
217
-
218
- Element opt-out: `data-omega-no-translate`, unchanged. Collector fixes vs UJM:
219
- `aria-describedby`/`aria-labelledby` are NOT collected (ID refs), `value`
220
- only on button-type inputs (hidden-input tokens stay intact).
221
-
222
- ### Framework-shipped default-page translations ([#621](https://github.com/Omega-JS-Stack/omega/issues/621))
223
-
224
- The default pages above render the SAME chrome on every brand, so the framework
225
- translates them ONCE and ships the result: `packages/web/translations/{lang}/pages/{route}.json`,
226
- the identical `{lang}/{namespace}.json` shape as a consumer's own cache (same
227
- loader, same `sha256(source)[:12]` keys, same prune-on-save, hand-fixable the
228
- same way), committed to the package and published under `files`.
229
-
230
- The keys are brand-NEUTRAL. The generator renders with a fixture brand and
231
- replaces every occurrence of it with the sentinel `__OMEGA_BRAND__` before
232
- hashing; the read-through replaces the CONSUMER's `brand.name` with the same
233
- token before the lookup and puts it back on the way out, so "Sign in to MiniCo"
234
- and "Sign in to Acme" are one packaged entry (`src/translate/packaged-defaults.js`).
235
-
236
- Consumer side, on every pass — `omega build`, `--cached-only`, `omega translate`
237
- alike, since it never touches a provider:
238
-
239
- - Each default route gets its `dist/{lang}/…` copy with the same localized
240
- chrome, hreflang and sitemap entry as any other page. Link rewriting is the
241
- same pass too, which means links OUT to brand pages gain the language segment
242
- while links between two default routes (signin → signup) do not — those routes
243
- are excluded from rewriting, and that is unchanged from #605.
244
- - A string the package does not carry (copy the brand overrode, a page the
245
- framework has not regenerated for) stays in the source language and is
246
- COUNTED — one log line per route names the miss count. Never guessed at.
247
- - A brand whose NAME is a word the chrome itself uses ("Sign") still gets every
248
- string that does not interpolate the brand — the lookup falls back to the raw
249
- key when the sentinel-normalized one misses. The strings that DO interpolate
250
- it (`Sign in to Sign`) miss, and stay in the source language.
251
- - A route the package carries nothing for gets NO copy, so hreflang keeps
252
- telling the truth. That is how the legal boilerplate stays one language:
253
- `terms`/`privacy`/`cookies` are deliberately not generated.
254
- - A configured language the package does not ship is one log line for the whole
255
- run, not an error — those routes stay in the source language.
256
- - A brand's `translation.include` list never touches the framework's default
257
- pages: it scopes the brand's OWN pages, and the framework's chrome is
258
- translated once, on the framework side.
259
-
260
- **Shipped set: `es`, `fa`.** Regenerating, or extending the set, is one command
261
- in `packages/web` (the ONLY place the framework's own pages ever reach a
262
- provider):
263
-
264
- ```bash
265
- npm run translate:defaults # the shipped set
266
- npm run translate:defaults -- --languages es,fa,de # …plus a new one
267
- ```
268
-
269
- It renders the defaults tree through the real production build against a
270
- throwaway consumer (no brand repo involved), harvests with the same collector
271
- the pass uses, translates ONLY the strings the packaged cache is missing —
272
- across all routes at once, so the header/footer chrome every default page
273
- repeats is paid for exactly once — and writes the files back. Idempotent: a
274
- re-run costs nothing, adding a language costs only that language. A provider
275
- failure, or a translation that dropped the sentinel, STOPS the run and writes
276
- nothing.
277
-
278
- `dist/sitemap.xml` (emitted by the build in the source language only) is
279
- rewritten afterwards so it tells the same story: every PRODUCED copy joins it
280
- as its own `<url>`, and each entry of a translated set — source and copies
281
- alike — carries the full `xhtml:link rel="alternate"` list (`x-default` at the
282
- source language) plus the source entry's `lastmod`/`changefreq`/`priority`.
283
- Entries stay in loc byte order. The language-prefixed entries are owned by that
284
- pass: each run drops them all and re-emits only what it produced, so a skipped
285
- or failed pair is listed nowhere.
286
-
287
- The visitor-facing **language switcher** is the footer dropup in the shared
288
- base footer include (`_includes/frontend/sections/footer.html`, the base layer
289
- every theme inherits). It renders CLIENT-SIDE from the page's own
290
- `link[rel="alternate"][hreflang]` tags — the produced-only SSOT above — so the
291
- menu can never offer a copy that was not written: `core/js/core/language-switcher.js`
292
- drops `x-default`, labels each row with its native name (`Intl.DisplayNames` in
293
- that language's own locale, upper-cased code as the fallback), marks
294
- `documentElement.lang` as current, and leaves the mount empty and hidden when
295
- fewer than two languages exist. Selecting a language is a plain link to that
296
- alternate's href — never a redirect or a negotiation.
297
-
298
- Not here yet: no default homepage exists in the D8 set, so brand sites
299
- translate their own `index` when they add one.
300
-
301
- ## Extension (`@omega.js/extension`)
302
-
303
- Build-mode gulp `translate` task (setup/dev builds only deploy):
304
-
305
- - **messages**: per-KEY incremental — unique `message` values without a cache
306
- entry translate (CWS limits ride the prompt as extra rules; violations warn
307
- with the file path to shorten). `dist/_locales/{lang}/messages.json` is
308
- COMPOSED from the EN source + cache (English fallback per missing key, so
309
- the file is always complete; developer `description` fields stay English).
310
- - **description**: whole-document per language →
311
- `translations/{lang}/description.md`, first line
312
- `<!-- omega:source <hash> -->` (stripped on read; source edit →
313
- re-translate). The package task ships them as store assets
314
- (`packaged/assets/description/{lang}.md`).
315
-
316
- Languages/provider come from resolved config — the old hardcoded 16-language
317
- list in `gulp/config/locales.js` is gone (only the CWS `limits` remain there).
318
-
319
- ## Testing
320
-
321
- - devkit `test/translate.test.js` — engine protocol, providers, cache,
322
- language SSOT, settings reader (fake `send`).
323
- - web `test/translate.test.js` — handcrafted dist through the real pipeline:
324
- copies/chrome/links/exclusions/alternates/cache/override/only-filter, the
325
- produced-languages-only alternates, and the loud failure skip.
326
- - web `test/language-switcher.test.js` — the switcher's DOM read (x-default
327
- dropped, duplicates collapsed, current marked, escaping) and the built footer
328
- mount in classy and newsflash.
329
- - extension `build/translate.test.js` — compose + description marker glue.
330
- - Live canary (cp96, local Claude): omega-brand `/about` → es (102 strings,
331
- rerun 0 calls) and the extension's 4 messages (2 unique) + 2,703-char
332
- description → es, both idempotent; artifacts committed under each target's
333
- `translations/`.
@@ -1,61 +0,0 @@
1
- # Dependency updates (`omega update`)
2
-
3
- One shared implementation (`@omega.js/devkit/update`) behind every framework's `omega update` verb (aliases: `outdated`, `out` — npu's muscle memory), thin wiring in web/desktop/extension (router commands), backend (colon-style command class), and the manager (brand-root fan-out). Semantics mirror Ian's `npu out` (node-power-user): report first, apply deliberately, and never trust a brand-new release.
4
-
5
- ## The report (default — no flags)
6
-
7
- For each dependency of the target's `package.json` (prod + dev, grouped):
8
-
9
- | Column | Meaning |
10
- |---|---|
11
- | Current | the base version in `package.json` (`^1.2.3` → `1.2.3`) |
12
- | Installed | the physical `node_modules` copy (nearest, climbing — npm hoists in brand monorepos) |
13
- | Wanted | highest published version satisfying the range (npm-outdated semantics) |
14
- | Latest | the registry `dist-tags.latest` |
15
- | Bump | `patch` / `minor` / `major` — Current → Latest classification |
16
- | Released | Latest's publish date + age in days |
17
- | Status | `QUARANTINED` when Latest is younger than `--min-age` days (default **7**) and not already installed |
18
-
19
- Only rows needing attention print; a fully-current tree reports one line. Rows sort prod-first.
20
-
21
- **Quarantine (supply-chain caution, npu's `--min-age` semantics):** a release published < 7 days ago may be a compromised publish — it is flagged and **excluded from `--apply`**. `--min-age N` changes the window; `--min-age 0` or `--force-fresh` disables it. Unpublished packages (the pre-publish `@omega.js/*` set) report `not on the registry (unpublished?)` instead of a version row.
22
-
23
- **`file:`/`link:`/git specs are SKIPPED** with a dim note — they have no registry story. In the local era every brand's `@omega.js/*` dep is a `file:` spec, so the verb never touches the linked frameworks.
24
-
25
- ## Applying (`--apply`)
26
-
27
- - Default tier is **non-breaking**: each dep rides to its highest same-major version (npu's minor tier) — quarantined targets are held and listed.
28
- - **Majors are never auto-applied**: breaking jumps are listed as held; `--apply --major` opts in explicitly.
29
- - Installs run through **`npu install`** when npu is on the machine (Socket supply-chain firewall); otherwise plain `npm install` with a loud warning. Dev deps install with `--save-dev` in their own pass.
30
-
31
- ## The @omega.js family is pinned, and `omega update` is its ONE mover ([#794](https://github.com/Omega-JS-Stack/omega/issues/794))
32
-
33
- Every `@omega.js/*` spec the manager writes into a brand is an EXACT pin, never a
34
- caret: `"@omega.js/manager": "0.50.0"` at the brand root, `"@omega.js/<framework>":
35
- "0.50.0"` in each target, all at the manager's own version (the family ships
36
- lockstep — [publishing.md](publishing.md)). A caret would let one target float
37
- ahead alone on somebody's `npm update`, which is how a brand ends up serving two
38
- copies of `@omega.js/client` and validating one omega.json5 with two validators.
39
-
40
- Pinned, the only thing that moves a brand is `omega update --apply` at the brand
41
- ROOT (a bare run reports and installs nothing), and it moves every target — and
42
- the root's own manager pin — together. `--apply` installs an `@omega.js/*` dep with
43
- `--save-exact`, in its own command per dep group, so the mover never un-pins
44
- what it just moved (npm's default save-prefix would write `^<version>` back);
45
- every other dependency keeps npm's default prefix, because the pin is the
46
- FAMILY's rule and not a rule for the whole tree.
47
-
48
- The manager's boot check enforces the other half: a brand whose installed
49
- versions have drifted is refused before any service or dev leg runs
50
- ([../manager/brand.md](../manager/brand.md)). The local era is untouched — a
51
- `file:` spec has no registry story, so the verb skips it and the boot check
52
- exempts it. `omega i live` (the publish-day flip back off `file:` specs) writes
53
- the same exact pin ([local-dev.md](local-dev.md) § API surface).
54
-
55
- ## Brand root
56
-
57
- `omega update` at a brand root (manager) fans out over the brand's targets, cp251's deploy fan-out shape: same target discovery, same `--target=<name>[,<name>]` picker ([#780](https://github.com/Omega-JS-Stack/omega/issues/780)), every other flag forwarded verbatim, each target answering through its own framework's `update` verb. Unlike deploy, targets are **independent**: one failing target never blocks the rest (any failure still exits 1). The brand-root shell `package.json` rides the walk as its LAST leg ([#794](https://github.com/Omega-JS-Stack/omega/issues/794)), scoped to the one `@omega.js/*` dependency it carries (`@omega.js/manager`) and run in-process through the same devkit implementation (there is no framework bin at the root to spawn; it would dispatch straight back into this command). A brand's own root tooling is never touched, and a picked run (`--target=`) skips the root, because the picker names targets. Without that leg a manager-behind brand could never heal itself: the boot check would refuse every verb, and the fix it names would move every target except the one that was wrong.
58
-
59
- ## Testing
60
-
61
- Registry lookups, the clock, npu detection, and exec are all injectable — the devkit suite (`packages/devkit/test/update.test.js`) runs entirely offline against fixture packuments with a frozen clock; the manager fan-out test spawns fake framework bins; framework structure tests pin the wiring. The live path is the thin defaults (native `fetch` of the full packument — the abbreviated form carries no publish times).