@omega.js/manager 0.1.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 (416) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/LICENSE +98 -0
  3. package/README.md +165 -0
  4. package/bin/omega +2 -0
  5. package/bin/omg +2 -0
  6. package/claude-plugin/.claude-plugin/plugin.json +11 -0
  7. package/claude-plugin/.mcp.json +9 -0
  8. package/claude-plugin/README.md +139 -0
  9. package/claude-plugin/hooks/gate/mark.sh +58 -0
  10. package/claude-plugin/hooks/gate/run.sh +97 -0
  11. package/claude-plugin/hooks/guard/run.sh +249 -0
  12. package/claude-plugin/hooks/hooks.json +63 -0
  13. package/claude-plugin/hooks/inject/run.sh +127 -0
  14. package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
  15. package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
  16. package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
  17. package/claude-plugin/hooks/quality/run.sh +132 -0
  18. package/claude-plugin/hooks/shape/run.sh +45 -0
  19. package/claude-plugin/mcp-router-launch.js +29 -0
  20. package/claude-plugin/skills/README.md +48 -0
  21. package/claude-plugin/skills/accessibility/SKILL.md +31 -0
  22. package/claude-plugin/skills/analytics/SKILL.md +30 -0
  23. package/claude-plugin/skills/backend/SKILL.md +25 -0
  24. package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
  25. package/claude-plugin/skills/browser/SKILL.md +64 -0
  26. package/claude-plugin/skills/client/SKILL.md +24 -0
  27. package/claude-plugin/skills/desktop/SKILL.md +25 -0
  28. package/claude-plugin/skills/extension/SKILL.md +25 -0
  29. package/claude-plugin/skills/main/SKILL.md +54 -0
  30. package/claude-plugin/skills/manager/SKILL.md +25 -0
  31. package/claude-plugin/skills/seo/SKILL.md +36 -0
  32. package/claude-plugin/skills/theme/SKILL.md +33 -0
  33. package/claude-plugin/skills/web/SKILL.md +29 -0
  34. package/dist/cli-run.js +34 -0
  35. package/dist/cli.js +29 -0
  36. package/dist/commands/build.js +17 -0
  37. package/dist/commands/clean.js +16 -0
  38. package/dist/commands/company.js +46 -0
  39. package/dist/commands/deploy.js +143 -0
  40. package/dist/commands/dev.js +437 -0
  41. package/dist/commands/devlog.js +25 -0
  42. package/dist/commands/help.js +48 -0
  43. package/dist/commands/manage.js +53 -0
  44. package/dist/commands/migrate.js +76 -0
  45. package/dist/commands/onboard.js +31 -0
  46. package/dist/commands/pipeline.js +319 -0
  47. package/dist/commands/test.js +380 -0
  48. package/dist/commands/update.js +128 -0
  49. package/dist/commands/version.js +8 -0
  50. package/dist/company-init.js +167 -0
  51. package/dist/company.js +283 -0
  52. package/dist/config.js +1359 -0
  53. package/dist/devlog/index.js +226 -0
  54. package/dist/devlog/lib/collect-commits.js +136 -0
  55. package/dist/devlog/lib/generate-post.js +201 -0
  56. package/dist/devlog/lib/ghostii.js +122 -0
  57. package/dist/devlog/lib/project-map.js +98 -0
  58. package/dist/devlog/lib/publish-website.js +88 -0
  59. package/dist/index.js +45 -0
  60. package/dist/lib/agents-md.js +201 -0
  61. package/dist/lib/analytics-secret.js +22 -0
  62. package/dist/lib/argv.js +21 -0
  63. package/dist/lib/auth-admin.js +120 -0
  64. package/dist/lib/automation-client.js +210 -0
  65. package/dist/lib/backend-marketing.js +49 -0
  66. package/dist/lib/brand.js +240 -0
  67. package/dist/lib/bundle-id.js +53 -0
  68. package/dist/lib/claude-settings.js +125 -0
  69. package/dist/lib/company-scaffold.js +213 -0
  70. package/dist/lib/company.js +227 -0
  71. package/dist/lib/config-flow.js +350 -0
  72. package/dist/lib/config-write.js +41 -0
  73. package/dist/lib/custom-target.js +75 -0
  74. package/dist/lib/domain-utils.js +19 -0
  75. package/dist/lib/duration.js +39 -0
  76. package/dist/lib/env-order.js +236 -0
  77. package/dist/lib/env-secret.js +78 -0
  78. package/dist/lib/firestore-rest.js +326 -0
  79. package/dist/lib/framework-bin.js +156 -0
  80. package/dist/lib/gitignore.js +63 -0
  81. package/dist/lib/google-auth.js +495 -0
  82. package/dist/lib/google-token.js +66 -0
  83. package/dist/lib/jwt.js +31 -0
  84. package/dist/lib/legacy-oauth.js +59 -0
  85. package/dist/lib/node-version.js +127 -0
  86. package/dist/lib/owner-plan.js +78 -0
  87. package/dist/lib/package-scripts.js +152 -0
  88. package/dist/lib/preflight.js +470 -0
  89. package/dist/lib/product-create.js +144 -0
  90. package/dist/lib/run-command.js +74 -0
  91. package/dist/lib/run-gates.js +70 -0
  92. package/dist/lib/run-output.js +42 -0
  93. package/dist/lib/run-summary.js +384 -0
  94. package/dist/lib/scaffold.js +427 -0
  95. package/dist/lib/service-input.js +207 -0
  96. package/dist/lib/service-runner.js +466 -0
  97. package/dist/lib/stale.js +24 -0
  98. package/dist/lib/target-selection.js +155 -0
  99. package/dist/lib/verb-fanout.js +128 -0
  100. package/dist/lib/verify-live.js +188 -0
  101. package/dist/manage.js +311 -0
  102. package/dist/omega-bin.js +7 -0
  103. package/dist/onboard.js +532 -0
  104. package/dist/services/account/ensure/users.js +259 -0
  105. package/dist/services/account/index.js +97 -0
  106. package/dist/services/account/lib/backend-client.js +107 -0
  107. package/dist/services/account/lib/password.js +36 -0
  108. package/dist/services/account/lib/resolve-password.js +100 -0
  109. package/dist/services/advertising/ensure/sites.js +101 -0
  110. package/dist/services/advertising/index.js +101 -0
  111. package/dist/services/advertising/lib/adsense-api.js +41 -0
  112. package/dist/services/ai/ensure/keys.js +21 -0
  113. package/dist/services/ai/index.js +36 -0
  114. package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
  115. package/dist/services/analytics/ensure/google-streams.js +256 -0
  116. package/dist/services/analytics/ensure/meta-pixel.js +22 -0
  117. package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
  118. package/dist/services/analytics/index.js +134 -0
  119. package/dist/services/analytics/lib/analytics-api.js +156 -0
  120. package/dist/services/analytics/lib/meta-api.js +83 -0
  121. package/dist/services/analytics/lib/pixel-account.js +78 -0
  122. package/dist/services/analytics/lib/pixel-provision.js +152 -0
  123. package/dist/services/analytics/lib/pixel-specs.js +57 -0
  124. package/dist/services/analytics/lib/pixel-token.js +88 -0
  125. package/dist/services/analytics/lib/property-flow.js +77 -0
  126. package/dist/services/analytics/lib/tiktok-api.js +157 -0
  127. package/dist/services/analytics/lib/tiktok-auth.js +153 -0
  128. package/dist/services/assets/ensure/logo-gen.js +68 -0
  129. package/dist/services/assets/index.js +109 -0
  130. package/dist/services/assets/lib/assets-config.js +168 -0
  131. package/dist/services/assets/lib/brandmark-api.js +160 -0
  132. package/dist/services/assets/lib/derived.js +113 -0
  133. package/dist/services/assets/lib/font-loader.js +67 -0
  134. package/dist/services/assets/lib/reconcile.js +122 -0
  135. package/dist/services/assets/lib/reset.js +118 -0
  136. package/dist/services/assets/lib/svg-logo-generator.js +154 -0
  137. package/dist/services/assets/lib/svg-to-black.js +32 -0
  138. package/dist/services/assets/write/favicons.js +82 -0
  139. package/dist/services/assets/write/icons.js +64 -0
  140. package/dist/services/assets/write/process.js +96 -0
  141. package/dist/services/assets/write/reconcile.js +30 -0
  142. package/dist/services/assets/write/social-icons.js +108 -0
  143. package/dist/services/assets/write/templates.js +345 -0
  144. package/dist/services/bookmark/ensure/sync.js +255 -0
  145. package/dist/services/bookmark/index.js +17 -0
  146. package/dist/services/campaigns/ensure/contact-person.js +40 -0
  147. package/dist/services/campaigns/ensure/custom-fields.js +84 -0
  148. package/dist/services/campaigns/ensure/domain-auth.js +92 -0
  149. package/dist/services/campaigns/ensure/event-webhook.js +89 -0
  150. package/dist/services/campaigns/ensure/link-branding.js +187 -0
  151. package/dist/services/campaigns/ensure/list.js +50 -0
  152. package/dist/services/campaigns/ensure/segments.js +109 -0
  153. package/dist/services/campaigns/ensure/sender-identity.js +153 -0
  154. package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
  155. package/dist/services/campaigns/index.js +79 -0
  156. package/dist/services/campaigns/lib/dns-sync.js +81 -0
  157. package/dist/services/campaigns/lib/segment-query.js +138 -0
  158. package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
  159. package/dist/services/captcha/ensure/site-key.js +83 -0
  160. package/dist/services/captcha/index.js +78 -0
  161. package/dist/services/captcha/lib/console-url.js +45 -0
  162. package/dist/services/captcha/lib/recaptcha-api.js +36 -0
  163. package/dist/services/certificates/ensure/api-key.js +22 -0
  164. package/dist/services/certificates/ensure/bundle-ids.js +115 -0
  165. package/dist/services/certificates/ensure/certificates.js +187 -0
  166. package/dist/services/certificates/ensure/profiles.js +143 -0
  167. package/dist/services/certificates/index.js +225 -0
  168. package/dist/services/certificates/lib/apple-api.js +183 -0
  169. package/dist/services/certificates/lib/certificate-manager.js +252 -0
  170. package/dist/services/certificates/lib/identifier-manager.js +107 -0
  171. package/dist/services/certificates/lib/keychain.js +135 -0
  172. package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
  173. package/dist/services/certificates/lib/profile-manager.js +115 -0
  174. package/dist/services/chat/data/baseline-knowledge.md +96 -0
  175. package/dist/services/chat/ensure/chat.js +106 -0
  176. package/dist/services/chat/ensure/user.js +45 -0
  177. package/dist/services/chat/index.js +139 -0
  178. package/dist/services/chat/lib/baseline-knowledge.js +137 -0
  179. package/dist/services/cloud/ensure/authentication.js +267 -0
  180. package/dist/services/cloud/ensure/billing.js +120 -0
  181. package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
  182. package/dist/services/cloud/ensure/database.js +60 -0
  183. package/dist/services/cloud/ensure/firestore.js +79 -0
  184. package/dist/services/cloud/ensure/functions.js +49 -0
  185. package/dist/services/cloud/ensure/hosting.js +398 -0
  186. package/dist/services/cloud/ensure/oauth-consent.js +248 -0
  187. package/dist/services/cloud/ensure/project-settings.js +72 -0
  188. package/dist/services/cloud/ensure/sdk-config.js +95 -0
  189. package/dist/services/cloud/ensure/service-account.js +152 -0
  190. package/dist/services/cloud/ensure/services.js +103 -0
  191. package/dist/services/cloud/ensure/storage.js +47 -0
  192. package/dist/services/cloud/index.js +130 -0
  193. package/dist/services/cloud/lib/access-heal.js +130 -0
  194. package/dist/services/cloud/lib/firebase-api.js +662 -0
  195. package/dist/services/cloud/lib/project-flow.js +102 -0
  196. package/dist/services/directory/ensure/entry.js +48 -0
  197. package/dist/services/directory/index.js +64 -0
  198. package/dist/services/directory/lib/blocks.js +104 -0
  199. package/dist/services/disperse/index.js +45 -0
  200. package/dist/services/disperse/write/certs.js +117 -0
  201. package/dist/services/domain/ensure/nameservers.js +179 -0
  202. package/dist/services/domain/index.js +69 -0
  203. package/dist/services/domain/lib/namecheap-api.js +167 -0
  204. package/dist/services/domain/lib/registrars.js +46 -0
  205. package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
  206. package/dist/services/edge/ensure/cache-rules.js +105 -0
  207. package/dist/services/edge/ensure/dns-records.js +304 -0
  208. package/dist/services/edge/ensure/email-routing.js +292 -0
  209. package/dist/services/edge/ensure/rules-configuration.js +98 -0
  210. package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
  211. package/dist/services/edge/ensure/rules-redirect.js +107 -0
  212. package/dist/services/edge/ensure/rules-response-headers.js +90 -0
  213. package/dist/services/edge/ensure/rules-security.js +142 -0
  214. package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
  215. package/dist/services/edge/ensure/workers.js +219 -0
  216. package/dist/services/edge/ensure/zone-settings.js +108 -0
  217. package/dist/services/edge/ensure/zone.js +183 -0
  218. package/dist/services/edge/index.js +73 -0
  219. package/dist/services/edge/lib/cloudflare-api.js +84 -0
  220. package/dist/services/edge/lib/dns-records-helpers.js +518 -0
  221. package/dist/services/edge/lib/read-cache.js +16 -0
  222. package/dist/services/edge/lib/ruleset-helper.js +108 -0
  223. package/dist/services/edge/workers/omega-api-proxy.js +43 -0
  224. package/dist/services/email/data/baseline-filter.md +4 -0
  225. package/dist/services/email/data/baseline-knowledge.md +86 -0
  226. package/dist/services/email/ensure/agent.js +107 -0
  227. package/dist/services/email/ensure/user.js +45 -0
  228. package/dist/services/email/index.js +138 -0
  229. package/dist/services/email/lib/baseline.js +82 -0
  230. package/dist/services/email/lib/knowledge-file.js +53 -0
  231. package/dist/services/forms/ensure/form.js +46 -0
  232. package/dist/services/forms/ensure/user.js +45 -0
  233. package/dist/services/forms/index.js +138 -0
  234. package/dist/services/migrations/ensure/notifications.js +189 -0
  235. package/dist/services/migrations/ensure/orders.js +34 -0
  236. package/dist/services/migrations/ensure/payment-provider.js +132 -0
  237. package/dist/services/migrations/ensure/payments-intents.js +34 -0
  238. package/dist/services/migrations/ensure/state-retirement.js +266 -0
  239. package/dist/services/migrations/ensure/targets-rename.js +124 -0
  240. package/dist/services/migrations/ensure/users.js +1176 -0
  241. package/dist/services/migrations/index.js +101 -0
  242. package/dist/services/migrations/lib/attribution-touch.js +64 -0
  243. package/dist/services/migrations/lib/ensure-metadata.js +144 -0
  244. package/dist/services/migrations/lib/migration-runner.js +473 -0
  245. package/dist/services/migrations/lib/sanitize-strings.js +112 -0
  246. package/dist/services/migrations/lib/schema-validator.js +154 -0
  247. package/dist/services/monitoring/ensure/dsn.js +54 -0
  248. package/dist/services/monitoring/ensure/projects.js +135 -0
  249. package/dist/services/monitoring/index.js +54 -0
  250. package/dist/services/monitoring/lib/sentry-api.js +94 -0
  251. package/dist/services/newsletter/ensure/custom-fields.js +90 -0
  252. package/dist/services/newsletter/ensure/publication.js +94 -0
  253. package/dist/services/newsletter/ensure/segments.js +140 -0
  254. package/dist/services/newsletter/ensure/webhook.js +108 -0
  255. package/dist/services/newsletter/index.js +64 -0
  256. package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
  257. package/dist/services/newsletter/lib/segment-automation.js +577 -0
  258. package/dist/services/payment/ensure/chargebee-account.js +30 -0
  259. package/dist/services/payment/ensure/chargebee-products.js +359 -0
  260. package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
  261. package/dist/services/payment/ensure/paypal-account.js +36 -0
  262. package/dist/services/payment/ensure/paypal-products.js +374 -0
  263. package/dist/services/payment/ensure/paypal-webhook.js +128 -0
  264. package/dist/services/payment/ensure/stripe-account.js +93 -0
  265. package/dist/services/payment/ensure/stripe-disputes.js +56 -0
  266. package/dist/services/payment/ensure/stripe-products.js +245 -0
  267. package/dist/services/payment/ensure/stripe-radar.js +74 -0
  268. package/dist/services/payment/ensure/stripe-webhook.js +130 -0
  269. package/dist/services/payment/index.js +163 -0
  270. package/dist/services/payment/lib/chargebee-api.js +338 -0
  271. package/dist/services/payment/lib/payment-utils.js +116 -0
  272. package/dist/services/payment/lib/paypal-api.js +354 -0
  273. package/dist/services/payment/lib/provider-setup.js +134 -0
  274. package/dist/services/payment/lib/stripe-api.js +152 -0
  275. package/dist/services/repo/ensure/org.js +70 -0
  276. package/dist/services/repo/ensure/pages.js +72 -0
  277. package/dist/services/repo/ensure/repo.js +90 -0
  278. package/dist/services/repo/index.js +52 -0
  279. package/dist/services/repo/lib/github-api.js +196 -0
  280. package/dist/services/search/ensure/ga-link.js +57 -0
  281. package/dist/services/search/ensure/property.js +137 -0
  282. package/dist/services/search/ensure/sitemaps.js +70 -0
  283. package/dist/services/search/index.js +61 -0
  284. package/dist/services/search/lib/search-console-api.js +92 -0
  285. package/dist/services/seo/ensure/github-repos.js +271 -0
  286. package/dist/services/seo/index.js +55 -0
  287. package/dist/services/seo/lib/gh-api.js +161 -0
  288. package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
  289. package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
  290. package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
  291. package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
  292. package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
  293. package/dist/services/seo/templates/index.js +57 -0
  294. package/dist/services/server/ensure/brands.js +63 -0
  295. package/dist/services/server/index.js +42 -0
  296. package/dist/services/testing/ensure/target-checks.js +97 -0
  297. package/dist/services/testing/index.js +11 -0
  298. package/dist/services/testing/lib/checks.js +467 -0
  299. package/dist/services/update/index.js +20 -0
  300. package/dist/services/update/lib/cache.js +59 -0
  301. package/dist/services/update/lib/fingerprint.js +157 -0
  302. package/dist/services/update/write/targets.js +206 -0
  303. package/dist/services/workspace/ensure/agents.js +42 -0
  304. package/dist/services/workspace/ensure/claude-settings.js +34 -0
  305. package/dist/services/workspace/ensure/config.js +54 -0
  306. package/dist/services/workspace/ensure/defaults.js +60 -0
  307. package/dist/services/workspace/ensure/env-keys.js +55 -0
  308. package/dist/services/workspace/ensure/env-order.js +66 -0
  309. package/dist/services/workspace/ensure/env-rules.js +97 -0
  310. package/dist/services/workspace/ensure/gitignore.js +18 -0
  311. package/dist/services/workspace/ensure/scripts.js +126 -0
  312. package/dist/services/workspace/ensure/structure.js +97 -0
  313. package/dist/services/workspace/ensure/translation-sdk.js +148 -0
  314. package/dist/services/workspace/ensure/workflows.js +54 -0
  315. package/dist/services/workspace/index.js +8 -0
  316. package/dist/vendor/account/engine.js +182 -0
  317. package/dist/vendor/account/features.js +220 -0
  318. package/dist/vendor/account/index.js +53 -0
  319. package/dist/vendor/account/schema.js +272 -0
  320. package/dist/vendor/account/subscription.js +38 -0
  321. package/dist/vendor/config/company.js +31 -0
  322. package/dist/vendor/config/defaults.js +173 -0
  323. package/dist/vendor/config/demo.js +18 -0
  324. package/dist/vendor/config/desktop-artifacts.js +110 -0
  325. package/dist/vendor/config/edit.js +769 -0
  326. package/dist/vendor/config/env-delivery.js +145 -0
  327. package/dist/vendor/config/env-rules.js +93 -0
  328. package/dist/vendor/config/env-schema.js +1078 -0
  329. package/dist/vendor/config/env.js +445 -0
  330. package/dist/vendor/config/hooks.js +97 -0
  331. package/dist/vendor/config/index.js +237 -0
  332. package/dist/vendor/config/instances.js +208 -0
  333. package/dist/vendor/config/load.js +490 -0
  334. package/dist/vendor/config/merge.js +68 -0
  335. package/dist/vendor/config/order.js +139 -0
  336. package/dist/vendor/config/ports.js +374 -0
  337. package/dist/vendor/config/providers.js +32 -0
  338. package/dist/vendor/config/repo.js +142 -0
  339. package/dist/vendor/config/retired-keys.js +430 -0
  340. package/dist/vendor/config/schema.js +1610 -0
  341. package/dist/vendor/config/secrets.js +50 -0
  342. package/dist/vendor/config/seed.js +34 -0
  343. package/dist/vendor/config/site-global.js +205 -0
  344. package/dist/vendor/config/validate.js +554 -0
  345. package/dist/vendor/config/winback.js +61 -0
  346. package/dist/vendor/devkit/attach-log-file.js +262 -0
  347. package/dist/vendor/devkit/certs.js +199 -0
  348. package/dist/vendor/devkit/ci-workflows.js +520 -0
  349. package/dist/vendor/devkit/cli-router.js +156 -0
  350. package/dist/vendor/devkit/command-path.js +46 -0
  351. package/dist/vendor/devkit/deploy-record.js +180 -0
  352. package/dist/vendor/devkit/flows.js +317 -0
  353. package/dist/vendor/devkit/local-https.js +360 -0
  354. package/dist/vendor/devkit/local.js +1905 -0
  355. package/dist/vendor/devkit/logger.js +128 -0
  356. package/dist/vendor/devkit/omega-bin.js +345 -0
  357. package/dist/vendor/devkit/prompt.js +187 -0
  358. package/dist/vendor/devkit/safe-install.js +18 -0
  359. package/dist/vendor/devkit/stop-signals.js +28 -0
  360. package/dist/vendor/devkit/test/scope.js +162 -0
  361. package/dist/vendor/devkit/translate/cache.js +84 -0
  362. package/dist/vendor/devkit/translate/engine.js +243 -0
  363. package/dist/vendor/devkit/translate/index.js +49 -0
  364. package/dist/vendor/devkit/translate/languages.js +134 -0
  365. package/dist/vendor/devkit/translate/providers.js +188 -0
  366. package/dist/vendor/devkit/update.js +569 -0
  367. package/docs/AGENTS.md +200 -0
  368. package/docs/account.md +45 -0
  369. package/docs/advertising.md +46 -0
  370. package/docs/ai.md +34 -0
  371. package/docs/analytics.md +69 -0
  372. package/docs/assets.md +57 -0
  373. package/docs/bookmark.md +26 -0
  374. package/docs/brand.md +151 -0
  375. package/docs/campaigns.md +96 -0
  376. package/docs/captcha.md +46 -0
  377. package/docs/certificates.md +68 -0
  378. package/docs/chat.md +47 -0
  379. package/docs/cloud.md +110 -0
  380. package/docs/company.md +64 -0
  381. package/docs/directory.md +140 -0
  382. package/docs/disperse.md +46 -0
  383. package/docs/domain.md +56 -0
  384. package/docs/edge.md +234 -0
  385. package/docs/email.md +42 -0
  386. package/docs/forms.md +48 -0
  387. package/docs/index.md +109 -0
  388. package/docs/migration.md +203 -0
  389. package/docs/migrations.md +56 -0
  390. package/docs/monitoring.md +41 -0
  391. package/docs/newsletter.md +48 -0
  392. package/docs/payment.md +83 -0
  393. package/docs/repo.md +48 -0
  394. package/docs/search.md +44 -0
  395. package/docs/seo.md +34 -0
  396. package/docs/server.md +37 -0
  397. package/docs/shared/agent-docs.md +89 -0
  398. package/docs/shared/analytics.md +612 -0
  399. package/docs/shared/brands.md +51 -0
  400. package/docs/shared/breaking-changes.md +497 -0
  401. package/docs/shared/config.md +1387 -0
  402. package/docs/shared/deploys.md +215 -0
  403. package/docs/shared/icons.md +201 -0
  404. package/docs/shared/local-dev.md +147 -0
  405. package/docs/shared/logging.md +202 -0
  406. package/docs/shared/monitoring.md +153 -0
  407. package/docs/shared/publishing.md +183 -0
  408. package/docs/shared/rulings.md +34 -0
  409. package/docs/shared/testing.md +147 -0
  410. package/docs/shared/theming.md +604 -0
  411. package/docs/shared/translation.md +291 -0
  412. package/docs/shared/updates.md +61 -0
  413. package/docs/testing.md +34 -0
  414. package/docs/update.md +36 -0
  415. package/docs/workspace.md +64 -0
  416. package/package.json +88 -0
@@ -0,0 +1,380 @@
1
+ /**
2
+ * `omega test` at a brand root — C5's brand layer: fan the test run out over
3
+ * the brand's targets, each in its own framework's hands, and then run the
4
+ * brand's OWN e2e lane.
5
+ *
6
+ * omega test → every target's PROJECT tests, then test/e2e/
7
+ * omega test framework: → every target's framework suite
8
+ * omega test full: → both sources, every target
9
+ * omega test routes/x → project filter, forwarded to every target
10
+ * (a target with no matching tests no-ops; a
11
+ * path NO target carries fails the run, #814)
12
+ * omega test web:pages/ → ONLY the web target — its framework suite, scoped
13
+ * omega test desktop: → ONLY the desktop target's framework suite
14
+ * omega test --target=web,backend → narrow ANY of the above to those targets
15
+ * omega test --extended → fanned out: every target runs its real-service suites
16
+ * omega test --lane=<name> → fanned out to the targets that DECLARE that lane
17
+ *
18
+ * Universal targets (bare paths, `framework:`/`omega:`/`mgr:`, `full:`,
19
+ * `project:`/`brand:`) forward to every target verbatim; per-framework ids
20
+ * (FRAMEWORK_IDS: `web:`, `backend:`, `desktop:`, `extension:`) route to
21
+ * the target owning that framework — the legacy short ids are retired. Unknown
22
+ * prefixes warn and are dropped; if nothing valid remains, every target runs
23
+ * bare (scope.js parity).
24
+ *
25
+ * `--target=<a,b>` is the TARGET picker, and it composes with every scope
26
+ * above rather than replacing any of them: a comma list of target keys ('web')
27
+ * or dir names ('website') narrowing which targets the run reaches. A
28
+ * per-framework id already names its target, so an id whose owner the picker
29
+ * excludes is a contradiction, not a narrowing — it refuses by name instead of
30
+ * running the empty intersection.
31
+ *
32
+ * MODE flags fan out ([#775](https://github.com/Omega-JS-Stack/omega/issues/775)):
33
+ * `--extended` (real external services) reaches every framework target, and
34
+ * `--lane=<name>` reaches the targets whose framework DECLARES that lane in
35
+ * its package.json `omega.testLanes` — a target that declares none prints one
36
+ * line and the run stays green, because an opt-in lane no framework serves is
37
+ * a lane that does not apply there, never a failure. Path-scope flags
38
+ * (`--layer`) stay target-level invocations.
39
+ *
40
+ * The BRAND E2E LANE (`<brandRoot>/test/e2e/run.js`) runs last, when it
41
+ * exists: one browser lane driving the brand's real pages against its real
42
+ * local stack, which is a brand-level surface no target owns. It is a runner
43
+ * script, so — exactly like a custom target's `test` script — it hears no
44
+ * scope vocabulary and no flags: a bare run reaches it, and a scoped,
45
+ * picked (`--target=`) or laned run never does.
46
+ *
47
+ * Targets run sequentially with streamed output; any failing target → exit 1.
48
+ */
49
+ const fs = require('node:fs');
50
+ const path = require('node:path');
51
+ const chalk = require('chalk').default;
52
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
53
+
54
+ const Logger = require('../vendor/devkit/logger.js');
55
+ const { UNIVERSAL_FRAMEWORK_ALIASES, PROJECT_ALIASES, FULL_ALIASES, FRAMEWORK_IDS, FANOUT_ENV, NO_MATCH_EXIT_CODE, noMatchMessage, parseTestScope, isPathTargeted } = require('../vendor/devkit/test/scope.js');
56
+ const { resolveBrandRoot, discoverTargets } = require('../lib/brand.js');
57
+ const { resolveTargetRun, resolveFrameworkPackage } = require('../lib/framework-bin.js');
58
+ const { PICKER_FLAG, assertPickerFlags, assertKnownTargets, parseTargetTokens, targetMatches } = require('../lib/target-selection.js');
59
+ const { runCommand } = require('../lib/run-command.js');
60
+
61
+ // Prefixes forwarded to every target as-is (each target's own C5 parser interprets them)
62
+ const UNIVERSAL_PREFIXES = new Set([
63
+ ...UNIVERSAL_FRAMEWORK_ALIASES,
64
+ ...PROJECT_ALIASES,
65
+ ...FULL_ALIASES,
66
+ ]);
67
+
68
+ // id prefix → owning framework package ('desktop' → '@omega.js/desktop', …)
69
+ const ID_TO_FRAMEWORK = Object.fromEntries(
70
+ Object.entries(FRAMEWORK_IDS).flatMap(([pkg, ids]) => ids.map((id) => [id, pkg]))
71
+ );
72
+
73
+ // The brand's own e2e lane — ONE entry file, by convention, so the walk never
74
+ // has to guess which of a directory's files is the runner and which are its
75
+ // helpers (#775).
76
+ const BRAND_E2E_DIR = path.join('test', 'e2e');
77
+ const BRAND_E2E_ENTRY = path.join(BRAND_E2E_DIR, 'run.js');
78
+
79
+ // The fan-out's own verdict is a log line, not a report row: the report says
80
+ // what each target did, this says what the RUN means (#814).
81
+ const logger = new Logger('test');
82
+
83
+ /**
84
+ * Split raw targets into per-target routing: `shared` goes to every target,
85
+ * `perFramework[pkg]` only to the target owning that framework, `invalid`
86
+ * is warned and dropped.
87
+ */
88
+ function partitionTargets(rawTargets) {
89
+ const shared = [];
90
+ const perFramework = {};
91
+ const invalid = [];
92
+
93
+ for (const raw of rawTargets) {
94
+ const target = String(raw).trim();
95
+ if (!target) continue;
96
+
97
+ // Same prefix grammar as scope.js (lowercase-only keeps C:/ paths bare)
98
+ const match = target.match(/^([a-z-]+):/);
99
+
100
+ if (!match) {
101
+ shared.push(target);
102
+ } else if (UNIVERSAL_PREFIXES.has(match[1])) {
103
+ shared.push(target);
104
+ } else if (ID_TO_FRAMEWORK[match[1]]) {
105
+ const pkg = ID_TO_FRAMEWORK[match[1]];
106
+ (perFramework[pkg] = perFramework[pkg] || []).push(target);
107
+ } else {
108
+ invalid.push(target);
109
+ }
110
+ }
111
+
112
+ return { shared, perFramework, invalid };
113
+ }
114
+
115
+ /**
116
+ * The brand root's targets read through the SAME grammar a target's own runner
117
+ * reads them with, so "did this run name a path?" means one thing everywhere
118
+ * ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)). Every framework
119
+ * id is handed in as an alias, since at this layer they all name a source.
120
+ *
121
+ * @param {string[]} rawTargets - The positional targets, as typed
122
+ * @returns {object} A parseTestScope() result
123
+ */
124
+ function namedScope(rawTargets) {
125
+ return parseTestScope(rawTargets, { frameworkAliases: Object.keys(ID_TO_FRAMEWORK) });
126
+ }
127
+
128
+ /**
129
+ * The `--target=` picker: which discovered targets a run may reach.
130
+ * Tokens match a target's key ('web') or its dir name ('website') through the
131
+ * shared matcher every brand-root picker uses (lib/target-selection.js,
132
+ * which also names the flag: ONE `--target=` on every verb, #780).
133
+ *
134
+ * @param {Array} targets - the discovered target entries
135
+ * @param {string} [picker] - the raw --target value (comma list)
136
+ * @returns {{ tokens: string[], selected: Array }}
137
+ * @throws {Error} when a token matches no target
138
+ */
139
+ function pickTargets(targets, picker) {
140
+ const tokens = parseTargetTokens(picker);
141
+ if (tokens.length === 0) {
142
+ return { tokens, selected: targets };
143
+ }
144
+
145
+ assertKnownTargets(
146
+ tokens.filter((token) => !targets.some((entry) => targetMatches(entry, token))),
147
+ targets.map((entry) => entry.target || entry.name),
148
+ );
149
+ const selected = targets.filter((entry) => tokens.some((token) => targetMatches(entry, token)));
150
+
151
+ return { tokens, selected };
152
+ }
153
+
154
+ /**
155
+ * Does this target's framework declare `lane`? The framework's package.json
156
+ * `omega.testLanes` is the SSOT — a lane is the framework's to own, and the
157
+ * brand root only needs to know which targets it applies to.
158
+ *
159
+ * @param {object} entry - the discovered target entry
160
+ * @param {string} framework - the framework package name
161
+ * @param {string} lane - the --lane value
162
+ * @returns {boolean}
163
+ */
164
+ function declaresLane(entry, framework, lane) {
165
+ const resolved = resolveFrameworkPackage(entry.path, framework);
166
+ const lanes = resolved?.pkg?.omega?.testLanes;
167
+ return Array.isArray(lanes) && lanes.includes(lane);
168
+ }
169
+
170
+ module.exports = async (options) => {
171
+ assertPickerFlags(options);
172
+
173
+ const brandRoot = resolveBrandRoot(process.cwd());
174
+ if (!brandRoot) {
175
+ console.error(chalk.red('✗ Not inside a brand monorepo (no config/omega.json5 up the tree) — run inside a brand, or inside a target for that target\'s tests.'));
176
+ process.exitCode = 1;
177
+ return;
178
+ }
179
+
180
+ // Tee the whole fan-out to <brandRoot>/logs/test.log (#623) — which target
181
+ // ran which scope, and the aggregate verdict (each target's own suite output
182
+ // stays in targets/<target>/logs/test.log).
183
+ attachLogFile(path.join(brandRoot, 'logs', 'test.log'));
184
+
185
+ // Positional targets — tolerate both `omega-manager test x` (command token
186
+ // present) and flag-alias entry (`--test x`, no token).
187
+ const rawTargets = (options._ || []).map(String);
188
+ if (rawTargets[0] === 'test') rawTargets.shift();
189
+
190
+ const { shared, perFramework, invalid } = partitionTargets(rawTargets);
191
+ for (const bad of invalid) {
192
+ console.log(chalk.yellow(` ⚠ Unknown test scope prefix ignored: ${bad}`));
193
+ }
194
+
195
+ // Nothing valid → every target runs bare (its project tests), scope.js parity.
196
+ const runAllBare = shared.length === 0 && Object.keys(perFramework).length === 0;
197
+ const lane = options.lane ? String(options.lane) : null;
198
+ const extended = !!options.extended;
199
+
200
+ const discovered = discoverTargets(brandRoot).filter((entry) => entry.target || entry.custom);
201
+ if (discovered.length === 0) {
202
+ console.log(chalk.yellow('⚠ No target-mapped dirs under targets/ — nothing to test.'));
203
+ return;
204
+ }
205
+
206
+ const picked = pickTargets(discovered, options[PICKER_FLAG]);
207
+
208
+ console.log(chalk.bold(`\nOMEGA brand tests — ${path.basename(brandRoot)}`));
209
+
210
+ // ─── Plan: which targets run, with which forwarded ids ────────────────────
211
+ const runs = [];
212
+
213
+ // Resolved ONCE per target: the plan below and the --target/id contradiction
214
+ // check both need to know which framework owns which target.
215
+ const resolvedRuns = discovered.map((entry) => ({ entry, run: resolveTargetRun(entry, 'test') }));
216
+
217
+ // A per-framework id names its target; a picker that excludes that target
218
+ // contradicts it. Refuse by name rather than run the empty intersection —
219
+ // silently testing nothing is the outcome a green exit must never mean.
220
+ for (const [pkg, ids] of Object.entries(perFramework)) {
221
+ const owner = resolvedRuns.find((item) => item.run.framework === pkg);
222
+ if (!owner || picked.selected.includes(owner.entry)) continue;
223
+
224
+ const error = new Error(
225
+ `omega test: refusing --${PICKER_FLAG}=${picked.tokens.join(',')} beside the "${ids[0]}" scope — `
226
+ + `${owner.entry.dir} owns that framework and --${PICKER_FLAG} excludes it. Nothing ran.\n`
227
+ + 'Name the same target on both, or drop one of them.',
228
+ );
229
+ error.refusal = true;
230
+ throw error;
231
+ }
232
+
233
+ for (const { entry, run } of resolvedRuns) {
234
+ if (!picked.selected.includes(entry)) continue;
235
+
236
+ // A target whose tests ARE its own `npm run test` — a custom target
237
+ // (#603), or a backend in custom-server mode whose framework has no
238
+ // emulator lane to run (#584) — never hears the scope vocabulary: it is
239
+ // the frameworks', and means nothing to a package script. So a SCOPED run
240
+ // never addresses one, a bare run does, and nothing is forwarded.
241
+ if (run.kind === 'custom' || run.kind === 'skip') {
242
+ // A lane is scope too — an opt-in lane a framework declares means
243
+ // nothing to a package script, so a laned run never addresses one.
244
+ if (!runAllBare || lane) continue;
245
+
246
+ if (run.kind === 'skip') {
247
+ console.log(chalk.dim(` ⊘ ${entry.name}: ${run.detail} — skipped`));
248
+ continue;
249
+ }
250
+
251
+ runs.push({ entry, framework: 'custom', command: run.command, args: run.args, label: run.label });
252
+ continue;
253
+ }
254
+
255
+ if (run.kind === 'error') {
256
+ // Only an error if this target was (or would be) addressed
257
+ if (runAllBare || shared.length > 0) {
258
+ runs.push({ entry, error: run.detail });
259
+ }
260
+ continue;
261
+ }
262
+
263
+ // An opt-in lane reaches only the frameworks that serve it; the rest say
264
+ // so in one line and the run stays green (#775).
265
+ if (lane && !declaresLane(entry, run.framework, lane)) {
266
+ console.log(chalk.dim(` ⊘ ${entry.name}: no "${lane}" lane in ${run.framework} — skipped`));
267
+ continue;
268
+ }
269
+
270
+ const args = [...shared, ...(perFramework[run.framework] || [])];
271
+ if (!runAllBare && args.length === 0) continue; // targeted run, not addressed to this target
272
+
273
+ // MODE flags ride the same `forwarded` seam every other brand-root fan-out
274
+ // uses (commands/deploy.js, lib/verb-fanout.js), so the flags land where
275
+ // that one place decides they land. Re-resolved only when there ARE flags:
276
+ // a bare run has nothing to forward and keeps its first resolution.
277
+ const forwarded = [
278
+ ...(extended ? ['--extended'] : []),
279
+ ...(lane ? [`--lane=${lane}`] : []),
280
+ ];
281
+ const flagged = forwarded.length ? resolveTargetRun(entry, 'test', forwarded) : run;
282
+
283
+ runs.push({
284
+ entry,
285
+ framework: flagged.framework,
286
+ command: flagged.command,
287
+ args: [...flagged.args, ...args],
288
+ label: `omega test ${[...forwarded, ...args].join(' ')}`.trimEnd(),
289
+ // This target is being ASKED, not chosen: a path it does not carry is a
290
+ // no-op here, and the signal is what lets its CLI say so with a code of
291
+ // its own instead of failing the whole brand run (#814).
292
+ env: { [FANOUT_ENV]: '1' },
293
+ });
294
+ }
295
+
296
+ // ─── The brand's own e2e lane, after the targets ───────────────────────────
297
+ // A bare run only: it is a runner script with no scope vocabulary and no
298
+ // flags, so a scoped, picked or laned run is asking for something else.
299
+ const brandLane = path.join(brandRoot, BRAND_E2E_ENTRY);
300
+ if (runAllBare && !lane && picked.tokens.length === 0 && fs.existsSync(path.join(brandRoot, BRAND_E2E_DIR))) {
301
+ if (fs.existsSync(brandLane)) {
302
+ runs.push({
303
+ entry: { name: BRAND_E2E_DIR, path: brandRoot },
304
+ framework: 'brand',
305
+ command: process.execPath,
306
+ args: [brandLane],
307
+ label: `node ${BRAND_E2E_ENTRY}`,
308
+ });
309
+ } else {
310
+ console.log(chalk.dim(` ⊘ ${BRAND_E2E_DIR}: no ${path.basename(BRAND_E2E_ENTRY)} entry — skipped`));
311
+ }
312
+ }
313
+
314
+ if (runs.length === 0) {
315
+ console.log(chalk.yellow('⚠ No target matches the requested scope — nothing ran.'));
316
+
317
+ // Nothing ran AND a path was named: the brand carries no target that could
318
+ // even be asked for it, which is the same typo the target-level rule
319
+ // catches, so it fails here too ([#814](https://github.com/Omega-JS-Stack/omega/issues/814)).
320
+ // A bare prefix (`desktop:` with no path) names no file, so it keeps the
321
+ // warning above and an exit 0.
322
+ if (isPathTargeted(namedScope(rawTargets))) {
323
+ logger.error(noMatchMessage(rawTargets.join(' ')));
324
+ process.exitCode = 1;
325
+ }
326
+ return;
327
+ }
328
+
329
+ // ─── Execute sequentially, streaming each target's output ─────────────────
330
+ const summary = [];
331
+ let failed = false;
332
+
333
+ for (const [index, run] of runs.entries()) {
334
+ const label = `[${index + 1}/${runs.length}] ${run.entry.name}`;
335
+
336
+ if (run.error) {
337
+ console.log(chalk.red(`\n✗ ${label}: ${run.error}`));
338
+ summary.push({ name: run.entry.name, ok: false, detail: run.error });
339
+ failed = true;
340
+ continue;
341
+ }
342
+
343
+ console.log(chalk.cyan(`${`\n─── ${label} ${chalk.dim(`(${run.framework})`)} — ${run.label}`.trimEnd()} ───`));
344
+ const result = await runCommand(run.command, run.args, run.entry.path, run.env);
345
+
346
+ // The distinct no-match code (#814): this target does not carry the path
347
+ // the brand root forwarded, which is a no-op here, not a failure. The run
348
+ // as a whole still has to answer for it below.
349
+ const missed = !result.success && result.code === NO_MATCH_EXIT_CODE;
350
+
351
+ summary.push({ name: run.entry.name, ok: result.success, missed, detail: missed ? 'no test file matches' : result.error });
352
+ if (!result.success && !missed) failed = true;
353
+ }
354
+
355
+ // ─── Summary + aggregate exit ──────────────────────────────────────────────
356
+ console.log(chalk.bold('\nTest summary'));
357
+ for (const entry of summary) {
358
+ if (entry.missed) {
359
+ console.log(` ${chalk.dim('⊘')} ${entry.name} ${chalk.dim(`— ${entry.detail}`)}`);
360
+ continue;
361
+ }
362
+ console.log(entry.ok
363
+ ? ` ${chalk.green('✓')} ${entry.name}`
364
+ : ` ${chalk.red('✗')} ${entry.name} ${chalk.dim(`— ${entry.detail}`)}`);
365
+ }
366
+
367
+ // Every target missed: the path exists nowhere in this brand, so the run
368
+ // tested nothing at all. One target carrying it is enough to be a real run
369
+ // (#814) — silently testing nothing is the outcome a green exit must never
370
+ // mean.
371
+ const misses = summary.filter((entry) => entry.missed);
372
+ if (!failed && misses.length > 0 && misses.length === summary.length) {
373
+ logger.error(noMatchMessage(rawTargets.join(' ')));
374
+ failed = true;
375
+ }
376
+
377
+ if (failed) {
378
+ process.exitCode = 1;
379
+ }
380
+ };
@@ -0,0 +1,128 @@
1
+ /**
2
+ * `omega update` at a brand root — fan the dependency-freshness verb out over
3
+ * the brand's targets (cp251's deploy fan-out shape: same target discovery, same
4
+ * --target= picker, same flag forwarding), each target reporting/applying
5
+ * through its OWN framework's `omega update` (all of them the one devkit
6
+ * implementation — npu-outdated semantics, 7-day release-age quarantine,
7
+ * file: specs skipped).
8
+ *
9
+ * omega update → every target, report only
10
+ * omega update --apply → apply the safe set per target
11
+ * omega update --target=backend → one target (target key or dir name)
12
+ * omega update --apply --major → include breaking jumps
13
+ *
14
+ * Unlike deploy, targets are INDEPENDENT here — a failing target never blocks the
15
+ * rest (no --continue-on-error needed); any failure still exits 1.
16
+ *
17
+ * The BRAND ROOT is the last leg of an unpicked run (#794): its shell manifest
18
+ * holds exactly one thing of ours, the `@omega.js/manager` pin, and without it
19
+ * a manager-behind brand could never self-heal — the lockstep gate would refuse
20
+ * every verb and the fix it names would move every target except the one that
21
+ * was wrong. That leg runs the same devkit implementation in-process (there is
22
+ * no framework bin to spawn at the root: it would dispatch straight back here)
23
+ * and is scoped to that one package by name, so a brand's own root tooling is
24
+ * never touched. `--target=` names TARGETS, so a picked run skips the root.
25
+ */
26
+ const path = require('node:path');
27
+ const chalk = require('chalk').default;
28
+ const jetpack = require('fs-jetpack');
29
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
30
+
31
+ const { findTarget } = require('../vendor/devkit/omega-bin.js');
32
+ // The module object, not the function: the root leg is the one caller that
33
+ // runs devkit's update in-process, and its test replaces this export.
34
+ const devkitUpdate = require('../vendor/devkit/update.js');
35
+ const { resolveBrandRoot, discoverTargets } = require('../lib/brand.js');
36
+ const { resolveFrameworkBin } = require('../lib/framework-bin.js');
37
+ const { runCommand } = require('../lib/run-command.js');
38
+ const { PICKER_FLAG, assertPickerFlags, selectTargets, buildForwardedFlags } = require('../lib/target-selection.js');
39
+
40
+ // The one @omega.js dependency a brand-root shell manifest carries
41
+ const ROOT_PACKAGE = '@omega.js/manager';
42
+
43
+ module.exports = async (options = {}) => {
44
+ assertPickerFlags(options);
45
+
46
+ const brandRoot = resolveBrandRoot(process.cwd());
47
+ if (!brandRoot) {
48
+ console.error(chalk.red('✗ Not inside a brand monorepo (no config/omega.json5 up the tree) — run inside a brand, or inside a target for that target\'s update.'));
49
+ process.exitCode = 1;
50
+ return;
51
+ }
52
+
53
+ // Tee the whole fan-out to <brandRoot>/logs/update.log (#623) — which target
54
+ // was checked, what it reported, what applied.
55
+ attachLogFile(path.join(brandRoot, 'logs', 'update.log'));
56
+
57
+ const targets = discoverTargets(brandRoot).filter((entry) => entry.target);
58
+ const { selected } = selectTargets({ targets, target: options[PICKER_FLAG] });
59
+
60
+ if (selected.length === 0) {
61
+ console.error(chalk.red('✗ This brand has no targets under targets/ — nothing checked.'));
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+
66
+ const forwarded = buildForwardedFlags(options);
67
+
68
+ console.log(chalk.bold(`\nOMEGA brand update — ${path.basename(brandRoot)} ${chalk.dim(`(${selected.map((entry) => entry.target).join(', ')})`)}`));
69
+
70
+ // ─── Fan out, streaming each target's report — targets are independent ─────
71
+ const summary = [];
72
+
73
+ for (const [index, entry] of selected.entries()) {
74
+ const label = `[${index + 1}/${selected.length}] ${entry.name}`;
75
+ const target = findTarget(entry.path);
76
+
77
+ if (!target || target.kind !== 'framework') {
78
+ console.log(chalk.red(`\n✗ ${label}: no framework dependency detected (target-root package.json)`));
79
+ summary.push({ name: entry.name, ok: false, detail: 'no framework dependency detected' });
80
+ continue;
81
+ }
82
+
83
+ const binPath = resolveFrameworkBin(target.dir, target.name);
84
+ if (!binPath) {
85
+ console.log(chalk.red(`\n✗ ${label}: ${target.name} is not installed (node_modules climb from ${target.dir} found no bin)`));
86
+ summary.push({ name: entry.name, ok: false, detail: `${target.name} is not installed` });
87
+ continue;
88
+ }
89
+
90
+ console.log(chalk.cyan(`${`\n─── ${label} ${chalk.dim(`(${target.name})`)} — omega update ${forwarded.join(' ')}`.trimEnd()} ───`));
91
+ const result = await runCommand(process.execPath, [binPath, 'update', ...forwarded], entry.path);
92
+ summary.push({ name: entry.name, ok: result.success, detail: result.error });
93
+ }
94
+
95
+ // ─── The brand root: its @omega.js/manager pin, and nothing else ───────────
96
+ const rootManifest = jetpack.read(path.join(brandRoot, 'package.json'), 'json') || {};
97
+ const rootSpec = rootManifest.dependencies?.[ROOT_PACKAGE] || rootManifest.devDependencies?.[ROOT_PACKAGE];
98
+
99
+ if (!options[PICKER_FLAG] && rootSpec) {
100
+ console.log(chalk.cyan(`${`\n─── [root] brand root ${chalk.dim(`(${ROOT_PACKAGE})`)} — omega update ${forwarded.join(' ')}`.trimEnd()} ───`));
101
+ try {
102
+ await devkitUpdate.runUpdate({
103
+ dir: brandRoot,
104
+ only: [ROOT_PACKAGE],
105
+ apply: options.apply,
106
+ major: options.major,
107
+ minAge: options.minAge ?? options['min-age'],
108
+ forceFresh: options.forceFresh || options['force-fresh'],
109
+ });
110
+ summary.push({ name: 'brand root', ok: true });
111
+ } catch (error) {
112
+ console.log(chalk.red(`✗ brand root: ${error.message}`));
113
+ summary.push({ name: 'brand root', ok: false, detail: error.message });
114
+ }
115
+ }
116
+
117
+ // ─── Summary + aggregate exit ──────────────────────────────────────────────
118
+ console.log(chalk.bold('\nUpdate summary'));
119
+ for (const entry of summary) {
120
+ console.log(entry.ok
121
+ ? ` ${chalk.green('✓')} ${entry.name}`
122
+ : ` ${chalk.red('✗')} ${entry.name} ${chalk.dim(`— ${entry.detail}`)}`);
123
+ }
124
+
125
+ if (summary.some((entry) => !entry.ok)) {
126
+ process.exitCode = 1;
127
+ }
128
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `omega-manager version` — print the package version.
3
+ */
4
+ const pkg = require('../../package.json');
5
+
6
+ module.exports = async () => {
7
+ console.log(`${pkg.name} v${pkg.version}`);
8
+ };
@@ -0,0 +1,167 @@
1
+ /**
2
+ * `omega company init` and `omega company adopt` — the COMPANY rung in two
3
+ * commands.
4
+ *
5
+ * A company workspace is a REPO, not a machine cache (machine-wide state stays
6
+ * in ~/.omega): the config layer every brand inherits, the `.env` that loads
7
+ * under every brand's own, and the shared Apple signing tree. `init`
8
+ * scaffolds that repo in one command; `adopt` is the ONE step a brand needs
9
+ * to join it — the `.omega/company.json` stamp the config layer already
10
+ * resolves (lib/company.js), which is what makes a brand-local run layer the
11
+ * company config, load the company `.env`, and share the signing tree.
12
+ *
13
+ * Both are idempotent: init fills gaps only (existing files are never
14
+ * touched) and adopt rewrites nothing when the marker already points here.
15
+ */
16
+
17
+ const fs = require('node:fs');
18
+ const path = require('node:path');
19
+ const chalk = require('chalk').default;
20
+ const jetpack = require('fs-jetpack');
21
+
22
+ const { hasOmegaConfig } = require('./vendor/config/index.js');
23
+
24
+ const { applyScaffoldPlan, printPlanResults } = require('./lib/scaffold.js');
25
+ const { COMPANY_DIRS, buildCompanyScaffoldPlan } = require('./lib/company-scaffold.js');
26
+ const {
27
+ isCompanyRoot,
28
+ resolveManageRoot,
29
+ discoverBrands,
30
+ loadCompanyConfig,
31
+ stampCompanyMarker,
32
+ } = require('./lib/company.js');
33
+
34
+ /**
35
+ * Create the directories a company workspace owns (the signing tree, the
36
+ * default brands root). Empty dirs carry no bytes, so this is a no-op on
37
+ * every rerun.
38
+ *
39
+ * @returns {string[]} - The dirs that did not exist yet
40
+ */
41
+ function ensureCompanyDirs(companyRoot) {
42
+ const created = [];
43
+
44
+ for (const relative of COMPANY_DIRS) {
45
+ const target = path.join(companyRoot, relative);
46
+ if (!jetpack.exists(target)) {
47
+ created.push(relative);
48
+ }
49
+ jetpack.dir(target);
50
+ }
51
+
52
+ return created;
53
+ }
54
+
55
+ /**
56
+ * Scaffold a company workspace at `dir`.
57
+ *
58
+ * @param {string} dir - Absolute directory to make a company root
59
+ * @returns {{ companyRoot: string, created: string[], kept: string[], dirs: string[] }}
60
+ */
61
+ function runCompanyInit(dir) {
62
+ const companyRoot = path.resolve(dir);
63
+ const name = path.basename(companyRoot);
64
+
65
+ console.log(chalk.bold.cyan('OMEGA Manager — Company workspace'));
66
+ console.log('');
67
+ console.log(`${chalk.dim('→')} ${chalk.cyan(companyRoot)}`);
68
+ console.log('');
69
+
70
+ const results = applyScaffoldPlan(companyRoot, buildCompanyScaffoldPlan(name));
71
+ printPlanResults(results);
72
+
73
+ const dirs = ensureCompanyDirs(companyRoot);
74
+ for (const relative of dirs) {
75
+ console.log(` ${chalk.green('✓')} created ${chalk.cyan(`${relative}/`)}`);
76
+ }
77
+
78
+ // Prove it is actually a company root before calling it done — the `brands`
79
+ // key is what every other verb detects, and the layer must parse
80
+ const layer = loadCompanyConfig(companyRoot);
81
+ console.log('');
82
+ if (isCompanyRoot(companyRoot)) {
83
+ const keys = Object.keys(layer);
84
+ console.log(`${chalk.green('✓')} Company config loads ${chalk.dim(keys.length > 0 ? `(brands inherit: ${keys.join(', ')})` : '(no inherited keys yet — every section is commented out)')}`);
85
+ } else {
86
+ console.log(`${chalk.red('✗')} config/omega.json5 has no \`brands\` key — this directory will not be treated as a company root`);
87
+ }
88
+
89
+ console.log('');
90
+ console.log(chalk.bold('Next steps'));
91
+ console.log(` ${chalk.dim('1.')} Fill in ${chalk.cyan('config/omega.json5')} — every key there is a default its brands inherit`);
92
+ console.log(` ${chalk.dim('2.')} Put the shared secrets in ${chalk.cyan('.env')} ${chalk.dim('(it loads under every brand\'s own)')}`);
93
+ console.log(` ${chalk.dim('3.')} ${chalk.cyan('npx omega company adopt <brand-path>')} ${chalk.dim('— per existing brand (or `npx omega onboard` for a new one)')}`);
94
+ console.log(` ${chalk.dim('4.')} ${chalk.cyan('npx omega manage')} ${chalk.dim('— the full walk, once per managed brand')}`);
95
+ console.log('');
96
+
97
+ return { companyRoot, ...results, dirs };
98
+ }
99
+
100
+ /**
101
+ * Adopt a brand into the company workspace containing `cwd`: stamp its
102
+ * `.omega/company.json`, the ONE step a brand needs.
103
+ *
104
+ * @param {string} cwd - Where the command ran (must resolve to a company root)
105
+ * @param {string} brandPath - The brand root to adopt (relative to cwd or absolute)
106
+ * @returns {{ companyRoot: string, brandRoot: string, stamped: boolean, managed: boolean }}
107
+ */
108
+ function runCompanyAdopt(cwd, brandPath) {
109
+ const resolved = resolveManageRoot(cwd);
110
+ if (!resolved?.isCompany) {
111
+ throw new Error(
112
+ 'Not inside a company workspace — run `omega company init` here first '
113
+ + '(a company root is a directory whose config/omega.json5 has a `brands` key)',
114
+ );
115
+ }
116
+ if (!brandPath) {
117
+ throw new Error('Usage: omega company adopt <brand-path>');
118
+ }
119
+
120
+ const companyRoot = resolved.root;
121
+ const brandRoot = path.resolve(cwd, brandPath);
122
+
123
+ if (!hasOmegaConfig(brandRoot)) {
124
+ throw new Error(`Not a brand: ${brandRoot} — a brand root has a config/omega.json5`);
125
+ }
126
+ if (isCompanyRoot(brandRoot)) {
127
+ throw new Error(`${brandRoot} is a company workspace, not a brand — the hierarchy is one rung: company → brands`);
128
+ }
129
+
130
+ const stamped = stampCompanyMarker(brandRoot, companyRoot);
131
+
132
+ console.log(`${chalk.dim('→')} Company workspace: ${chalk.cyan(companyRoot)}`);
133
+ if (stamped) {
134
+ console.log(`${chalk.green('✓')} adopted ${chalk.cyan(brandRoot)} ${chalk.dim('→ .omega/company.json')}`);
135
+ } else {
136
+ console.log(`${chalk.dim('•')} ${chalk.dim(brandRoot)} ${chalk.dim('already adopted (marker unchanged)')}`);
137
+ }
138
+
139
+ const inherited = Object.keys(loadCompanyConfig(companyRoot));
140
+ console.log(` ${chalk.dim(inherited.length > 0 ? `inherits: ${inherited.join(', ')} (+ the company .env, + the shared signing tree)` : 'inherits: the company .env + the shared signing tree (its config sets no keys yet)')}`);
141
+
142
+ // The stamp is enough for BRAND-LOCAL runs, but a company-wide `omega
143
+ // manage` only walks what brands.roots discovers — say so rather than let
144
+ // an adopted-but-undiscovered brand look managed
145
+ const managed = isDiscovered(companyRoot, brandRoot);
146
+ if (!managed) {
147
+ console.log(chalk.yellow(`⚠ ${brandRoot} is outside this company's brands.roots — it inherits the company layer on its own runs, but company-wide runs won't include it (add its parent dir to brands.roots)`));
148
+ }
149
+
150
+ return { companyRoot, brandRoot, stamped, managed };
151
+ }
152
+
153
+ /**
154
+ * Does a company-wide run walk this brand? Discovery reads config, so a
155
+ * broken/incomplete brands.roots is reported by the run itself, never by
156
+ * adopt — an undiscoverable company simply can't answer the question.
157
+ */
158
+ function isDiscovered(companyRoot, brandRoot) {
159
+ try {
160
+ const real = fs.realpathSync(brandRoot);
161
+ return discoverBrands(companyRoot).brands.some((brand) => fs.realpathSync(brand.root) === real);
162
+ } catch {
163
+ return true;
164
+ }
165
+ }
166
+
167
+ module.exports = { runCompanyInit, runCompanyAdopt };