@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,46 @@
1
+ /**
2
+ * `omega-manager company <init|adopt>` — the COMPANY rung's own verb.
3
+ *
4
+ * omega company init [path] scaffold a company workspace (default: cwd)
5
+ * omega company adopt <brand-path> stamp a brand so it inherits this company
6
+ *
7
+ * Everything else about a company workspace rides the verbs it already has:
8
+ * `omega manage` from a company root fans out over its brands, `omega
9
+ * onboard` creates a new brand under brands.roots[0] and stamps it.
10
+ */
11
+ const chalk = require('chalk').default;
12
+
13
+ const { runCompanyInit, runCompanyAdopt } = require('../company-init.js');
14
+
15
+ const USAGE = [
16
+ 'Usage: omega company <command>',
17
+ '',
18
+ ' init [path] scaffold a company workspace (default: the current directory)',
19
+ ' adopt <brand-path> stamp a brand so it inherits this company workspace',
20
+ ].join('\n');
21
+
22
+ module.exports = async (options) => {
23
+ const subcommand = options._?.[1];
24
+
25
+ try {
26
+ if (subcommand === 'init') {
27
+ runCompanyInit(options._?.[2] || process.cwd());
28
+ return;
29
+ }
30
+
31
+ if (subcommand === 'adopt') {
32
+ runCompanyAdopt(process.cwd(), options._?.[2]);
33
+ return;
34
+ }
35
+
36
+ console.error(subcommand
37
+ ? `${chalk.red('❌ Unknown company command')} ${chalk.dim(`"${subcommand}"`)}\n\n${USAGE}`
38
+ : USAGE);
39
+ process.exitCode = 1;
40
+ } catch (error) {
41
+ console.error(`${chalk.red('❌ Error')}${chalk.dim(`: ${error.message}`)}`);
42
+ process.exitCode = 1;
43
+ }
44
+ };
45
+
46
+ module.exports.USAGE = USAGE;
@@ -0,0 +1,143 @@
1
+ /**
2
+ * `omega deploy` at a brand root — D13's brand layer: fan the DELIBERATE
3
+ * publish out over the brand's targets, each in its own framework's hands
4
+ * (each target's own `omega deploy` verb — web sync/dispatch or direct lane,
5
+ * backend `firebase deploy`, desktop release, extension publish; the full
6
+ * per-target contract is docs/shared/deploys.md).
7
+ *
8
+ * omega deploy → every target, backend first
9
+ * omega deploy --target=backend → one target (target key or dir name)
10
+ * omega deploy --target=web,backend → explicit set
11
+ * omega deploy --dry-run → forwarded — each target prints its plan
12
+ *
13
+ * ORDER: the DELIVERY lane first (#678) — the same `BOOT_SERVICES` walk an
14
+ * `omega dev` boot runs, so config, assets and certs reach the targets before
15
+ * anything publishes them — then backend, then web, then the rest: the API
16
+ * must be live before the site that points at it. Every flag but --target=
17
+ * forwards verbatim to each target's framework deploy (--dry-run, --no-sync,
18
+ * --direct, --platforms, …); targets run sequentially with streamed output. A
19
+ * failing target STOPS the run (a broken API is no base for the site) unless
20
+ * --continue-on-error; any failure → exit 1. A --target= token matching
21
+ * nothing is an error, never a deploy-everything fallback — and deploys stay deliberate:
22
+ * nothing invokes this command but the human-typed verb (D13).
23
+ */
24
+ const path = require('node:path');
25
+ const chalk = require('chalk').default;
26
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
27
+
28
+ const { runManage } = require('../manage.js');
29
+ const { resolveBrandRoot, discoverTargets } = require('../lib/brand.js');
30
+ const { resolveTargetRun } = require('../lib/framework-bin.js');
31
+ const { runCommand } = require('../lib/run-command.js');
32
+ const { DEPLOY_ORDER, PICKER_FLAG, assertPickerFlags, selectTargets, buildForwardedFlags } = require('../lib/target-selection.js');
33
+
34
+ module.exports = async (options = {}) => {
35
+ assertPickerFlags(options);
36
+
37
+ const brandRoot = resolveBrandRoot(process.cwd());
38
+ if (!brandRoot) {
39
+ 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 deploy.'));
40
+ process.exitCode = 1;
41
+ return;
42
+ }
43
+
44
+ // Tee the whole fan-out — delivery lane included — to
45
+ // <brandRoot>/logs/deploy.log (#623): the publish verdict on disk. Only the
46
+ // backend keeps its own dist/deploy.log; this file is the one full record.
47
+ attachLogFile(path.join(brandRoot, 'logs', 'deploy.log'));
48
+
49
+ const targets = discoverTargets(brandRoot).filter((entry) => entry.target || entry.custom);
50
+ const { selected } = selectTargets({ targets, target: options[PICKER_FLAG] });
51
+
52
+ if (selected.length === 0) {
53
+ // Only an empty brand reaches here: a picker token that named nothing
54
+ // already stopped the run in the selector (#780).
55
+ console.error(chalk.red('✗ This brand has no targets under targets/ — nothing deployed.'));
56
+ process.exitCode = 1;
57
+ return;
58
+ }
59
+
60
+ const forwarded = buildForwardedFlags(options);
61
+ const continueOnError = !!(options['continue-on-error'] || options.continueOnError);
62
+ const dryRun = !!(options['dry-run'] || options.dryRun);
63
+
64
+ console.log(chalk.bold(`\nOMEGA brand deploy — ${path.basename(brandRoot)} ${chalk.dim(`(${selected.map((entry) => entry.target || entry.name).join(' → ')})`)}`));
65
+
66
+ // ─── Delivery lane, once, before the fan-out ───────────────────────────────
67
+ // Brand inputs (config, assets, certs) reach a target through ONE step
68
+ // (#678), and a deploy is one of its two triggers: the lane `omega dev`
69
+ // boots is asked for BY NAME here, so the service list can only ever be
70
+ // config.js's BOOT_SERVICES — never a second copy that drifts from it. A
71
+ // publish must not ship inputs a manage run happened to be current on.
72
+ console.log(chalk.cyan(`\n─── delivery lane ${chalk.dim('(brand inputs → targets)')} ───`));
73
+ const delivery = await runManage(brandRoot, { lane: 'boot', dryRun });
74
+ if (delivery.hasErrors) {
75
+ console.error(chalk.red('\n✗ The delivery lane reported errors — nothing deployed (fix them above, then deploy again).'));
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+
80
+ // ─── Execute in order, streaming each target's output ──────────────────────
81
+ const summary = [];
82
+ let failed = false;
83
+
84
+ for (const [index, entry] of selected.entries()) {
85
+ const label = `[${index + 1}/${selected.length}] ${entry.name}`;
86
+ const run = resolveTargetRun(entry, 'deploy', forwarded, { dryRun });
87
+
88
+ // A custom target that declares no deploy script steps aside loudly —
89
+ // there is nothing to publish and nothing broken (#603)
90
+ if (run.kind === 'skip') {
91
+ console.log(chalk.dim(`\n⊘ ${label}: ${run.detail} — skipped`));
92
+ continue;
93
+ }
94
+
95
+ // Its script cannot be handed --dry-run, so the dry run stops at the plan
96
+ if (run.kind === 'plan') {
97
+ console.log(chalk.dim(`\n⊘ ${label}: dry run — ${run.detail}`));
98
+ continue;
99
+ }
100
+
101
+ if (run.kind === 'error') {
102
+ console.log(chalk.red(`\n✗ ${label}: ${run.detail}`));
103
+ summary.push({ name: entry.name, ok: false, detail: run.detail });
104
+ failed = true;
105
+ if (!continueOnError) break;
106
+ continue;
107
+ }
108
+
109
+ console.log(chalk.cyan(`${`\n─── ${label} ${chalk.dim(`(${run.framework || 'custom'})`)} — ${run.label}`.trimEnd()} ───`));
110
+ const result = await runCommand(run.command, run.args, entry.path);
111
+
112
+ summary.push({ name: entry.name, ok: result.success, detail: result.error });
113
+ if (!result.success) {
114
+ failed = true;
115
+ if (!continueOnError) {
116
+ console.error(chalk.red(`\n✗ ${entry.name} deploy failed — stopping (later targets depend on it; --continue-on-error overrides)`));
117
+ break;
118
+ }
119
+ }
120
+ }
121
+
122
+ // ─── Summary + aggregate exit ──────────────────────────────────────────────
123
+ console.log(chalk.bold('\nDeploy summary'));
124
+ for (const entry of summary) {
125
+ console.log(entry.ok
126
+ ? ` ${chalk.green('✓')} ${entry.name}`
127
+ : ` ${chalk.red('✗')} ${entry.name} ${chalk.dim(`— ${entry.detail}`)}`);
128
+ }
129
+ const skipped = selected.length - summary.length;
130
+ if (skipped > 0) {
131
+ console.log(chalk.dim(` ⊘ ${skipped} target${skipped === 1 ? '' : 's'} not attempted after the failure`));
132
+ }
133
+
134
+ if (failed) {
135
+ process.exitCode = 1;
136
+ }
137
+ };
138
+
139
+ // Re-exported for readers that came to the deploy command for them — the one
140
+ // home is lib/target-selection.js.
141
+ module.exports.selectTargets = selectTargets;
142
+ module.exports.buildForwardedFlags = buildForwardedFlags;
143
+ module.exports.DEPLOY_ORDER = DEPLOY_ORDER;
@@ -0,0 +1,437 @@
1
+ /**
2
+ * `omega dev` (brand root) — ONE command boots the local stack: the website
3
+ * dev server AND the backend emulator suite together, each spawned in its
4
+ * own target with its own Node (web/backend pin different majors), output
5
+ * line-prefixed per target, one Ctrl-C killing everything.
6
+ *
7
+ * Target selection (Ian 2026-07-16): the default set is web + backend — the
8
+ * local web loop. GUI/watcher targets (desktop opens an Electron window,
9
+ * extension runs a build watcher) never boot unless asked.
10
+ * omega dev web + backend
11
+ * omega dev --target=web one leg (target key or dir name)
12
+ * omega dev --target=web,backend explicit set
13
+ * omega dev --all every target with a dev leg
14
+ * omega dev --full boot on the WHOLE manage walk, not the lane
15
+ *
16
+ * Boot order: the freshness sweep first (one dist check for every lane), then
17
+ * a manage cycle — the boot lane (workspace, assets, disperse: the local
18
+ * redistribution the legs consume), then the legs. See docs/shared/local-dev.md
19
+ * for what refreshes when.
20
+ *
21
+ * Port coordination is already solved (N7): the backend leg publishes its
22
+ * emulator ports; the web leg reads them and bakes dev.ports into pages —
23
+ * order tolerant, but backend boots first here so the fast path wins.
24
+ */
25
+
26
+ // Libraries
27
+ const path = require('node:path');
28
+ const { spawn } = require('node:child_process');
29
+ const chalk = require('chalk').default;
30
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
31
+ const { findTarget } = require('../vendor/devkit/omega-bin.js');
32
+ const { freshnessSweep, resolveLinkedMonorepo, startMonorepoWatch } = require('../vendor/devkit/local.js');
33
+ const { mkcertCaRootPem } = require('../vendor/devkit/local-https.js');
34
+ const { STOP_SIGNALS } = require('../vendor/devkit/stop-signals.js');
35
+
36
+ // Local
37
+ const { runManage } = require('../manage.js');
38
+ const { resolveBrandRoot, discoverTargets } = require('../lib/brand.js');
39
+ const { assertFamilyVersions } = require('../lib/preflight.js');
40
+ const { targetScripts } = require('../lib/custom-target.js');
41
+ const { resolveTargetNode, nodeEnvFor } = require('../lib/node-version.js');
42
+ const { PICKER_FLAG, assertPickerFlags, assertKnownTargets, parseTargetTokens, targetMatches } = require('../lib/target-selection.js');
43
+
44
+ // Target → the npm leg that IS local dev for that target
45
+ const DEV_LEGS = {
46
+ web: ['npm', 'run', 'start'], // omega dev — watch + serve (:4000)
47
+ backend: ['npm', 'run', 'emulator'], // omega emulator — FULL suite + seeded personas
48
+ desktop: ['npm', 'run', 'start'], // opt-in: opens an Electron window
49
+ extension: ['npm', 'run', 'start'], // opt-in: extension build watcher
50
+ };
51
+
52
+ // Every custom target's leg is the same one: its own `start` script (#603)
53
+ const CUSTOM_DEV_LEG = ['npm', 'run', 'start'];
54
+
55
+ /**
56
+ * The leg that IS local dev for one discovered target.
57
+ *
58
+ * A backend in custom-server mode (#584) has no Cloud Functions to emulate, so
59
+ * its leg is its own `start` — the same script a custom target boots with. Its
60
+ * server is the local stack's API either way, so it keeps the backend's place
61
+ * in the default set and its boot-first ordering.
62
+ *
63
+ * @param {{ target: string, custom?: boolean, projectType?: string }} entry
64
+ * @returns {string[]} argv for the leg
65
+ */
66
+ function devLegFor(entry) {
67
+ if (entry.custom || entry.projectType === 'custom') return CUSTOM_DEV_LEG;
68
+ return DEV_LEGS[entry.target] || CUSTOM_DEV_LEG;
69
+ }
70
+
71
+ /**
72
+ * Stop one dev leg. A leg is a CHAIN (npm run <leg> → the real server), so the
73
+ * SIGTERM goes to the leg's process group — signaling only the direct npm
74
+ * child leaves the grandchild (a firebase emulator) orphaned on pid 1, still
75
+ * holding its ports (#690). The direct kill is the fallback for a leg whose
76
+ * group is already gone.
77
+ */
78
+ const stopChild = (child, killGroup = (pid, signal) => process.kill(pid, signal)) => {
79
+ try {
80
+ killGroup(-child.pid, 'SIGTERM');
81
+ } catch {
82
+ try {
83
+ child.kill('SIGTERM');
84
+ } catch {
85
+ // already gone
86
+ }
87
+ }
88
+ };
89
+
90
+ // Booted without flags — the local web loop
91
+ const DEFAULT_TARGETS = ['web', 'backend'];
92
+
93
+ /**
94
+ * Pure target selection — which legs boot for a given flag set.
95
+ *
96
+ * Custom targets (#603) join the same fan-out: their leg is `npm run start`,
97
+ * and a custom target only reaches `custom` at all when its package.json
98
+ * declares that script — no script, no dev leg.
99
+ *
100
+ * @param {object} input
101
+ * @param {string[]} input.available - targets that have a dir in this brand
102
+ * @param {string[]} [input.custom] - custom target names with a `start` script
103
+ * @param {string} [input.target] - the --target= comma list: exact set to boot
104
+ * @param {boolean} [input.all] - start every target with a dev leg
105
+ * @returns {{ selected: string[], missing: string[] }}
106
+ * @throws {Error} when a --target= token names no dev leg
107
+ */
108
+ function selectDevTargets({ available, custom = [], target, all }) {
109
+ // A custom target is a first-class leg once it has a start script — the
110
+ // default set boots it beside web + backend (it is part of the local stack,
111
+ // never an opt-in GUI surface)
112
+ const hasLeg = (name) => Boolean(DEV_LEGS[name]) || custom.includes(name);
113
+ const defaults = [...DEFAULT_TARGETS, ...custom].filter((name) => available.includes(name));
114
+
115
+ const tokens = parseTargetTokens(target);
116
+ const requested = tokens.length > 0
117
+ ? tokens
118
+ : (all ? [...Object.keys(DEV_LEGS), ...custom] : defaults);
119
+
120
+ // A token naming no leg STOPS the boot (#780) — booting the rest of the set
121
+ // would serve a stack the human did not ask for. A named leg with no dir in
122
+ // this brand is a different thing: reported below, never invented.
123
+ assertKnownTargets(requested.filter((name) => !hasLeg(name)), [...Object.keys(DEV_LEGS), ...custom]);
124
+
125
+ const selected = requested.filter((name) => available.includes(name));
126
+ const missing = requested.filter((name) => !available.includes(name));
127
+
128
+ // Backend first: it publishes the emulator port map the web leg reads
129
+ selected.sort((a, b) => (a === 'backend' ? -1 : 0) - (b === 'backend' ? -1 : 0));
130
+
131
+ return { selected, missing };
132
+ }
133
+
134
+ /**
135
+ * Consecutive-duplicate collapser for ONE leg output stream (#230).
136
+ *
137
+ * The Firebase emulator re-prints its own infra lines once per function
138
+ * instance — "i functions: Loaded environment variables from .env." dozens of
139
+ * times in a row — which buries the lines a human is actually watching for.
140
+ * Repeats of the line just emitted are swallowed and counted; the count
141
+ * surfaces as ONE note when a different line arrives (or the stream ends, so a
142
+ * leg that goes quiet mid-run never eats the tail). The rule is structural —
143
+ * any consecutive duplicate on any leg — never a list of known noisy strings.
144
+ *
145
+ * Blank lines are exempt: a note standing in for a run of them reads louder
146
+ * than the blanks it replaced.
147
+ *
148
+ * Stateful because a stream is; pure otherwise — lines in, lines out.
149
+ * @returns {{ push: (line: string) => string[], flush: () => string[] }}
150
+ */
151
+ function createLineDeduper() {
152
+ let previous = null;
153
+ let repeats = 0;
154
+
155
+ const note = () => {
156
+ const pending = repeats > 0 ? [` (repeated ${repeats}×)`] : [];
157
+ repeats = 0;
158
+ return pending;
159
+ };
160
+
161
+ return {
162
+ push(line) {
163
+ if (line === previous && line.trim() !== '') {
164
+ repeats += 1;
165
+ return [];
166
+ }
167
+ const out = note();
168
+ previous = line;
169
+ out.push(line);
170
+ return out;
171
+ },
172
+ flush() {
173
+ previous = null;
174
+ return note();
175
+ },
176
+ };
177
+ }
178
+
179
+ module.exports = async (options = {}) => {
180
+ assertPickerFlags(options);
181
+
182
+ const brandRoot = resolveBrandRoot(process.cwd());
183
+ if (!brandRoot) {
184
+ console.error(chalk.red('✖ omega dev: no brand root found (looked for config/omega.json5 walking up from here)'));
185
+ process.exit(1);
186
+ }
187
+
188
+ // Tee the brand-level fan-out — the boot manage cycle AND every leg's
189
+ // prefixed output — to <brandRoot>/logs/dev.log (#197), its OWN file: a boot
190
+ // used to truncate logs/manage.log and take the last service walk's record
191
+ // with it, and the two are read for different questions (#231).
192
+ attachLogFile(path.join(brandRoot, 'logs', 'dev.log'));
193
+
194
+ // A custom target (#603) joins the fan-out under its own NAME, and only
195
+ // when its package.json declares a `start` script — the manager never
196
+ // invents a leg for it.
197
+ const discovered = discoverTargets(brandRoot);
198
+
199
+ // Lockstep (#794): the same gate the manage walk opens with, run here too —
200
+ // before the freshness sweep and before any leg spawns. A boot on a brand
201
+ // whose targets carry different @omega.js versions would serve two copies of
202
+ // the client and validate one omega.json5 with two validators; nothing
203
+ // downstream can see it, so the refusal belongs at the door.
204
+ assertFamilyVersions({ brandRoot, targets: discovered });
205
+
206
+ const customLegs = discovered.filter((entry) => entry.custom && targetScripts(entry.path).start);
207
+ const targets = [
208
+ ...discovered.filter((entry) => entry.target && DEV_LEGS[entry.target]),
209
+ ...customLegs.map((entry) => ({ ...entry, target: entry.name })),
210
+ ];
211
+
212
+ const custom = customLegs.map((entry) => entry.name);
213
+
214
+ // A --target= token names a target by KEY ('web') or by its dir name
215
+ // ('website') — the same two spellings every other brand-root verb takes
216
+ // (#780). The pairing lives in the discovered entries, so the dir spelling
217
+ // resolves to its key HERE, through the one shared matcher; a token that
218
+ // names nothing passes through untouched and the selector refuses it.
219
+ const picker = parseTargetTokens(options[PICKER_FLAG])
220
+ .map((token) => (targets.find((entry) => targetMatches(entry, token)) || {}).target || token)
221
+ .join(',');
222
+
223
+ const { selected, missing } = selectDevTargets({
224
+ available: targets.map((entry) => entry.target),
225
+ custom,
226
+ target: picker,
227
+ all: options.all,
228
+ });
229
+
230
+ missing.forEach((target) => {
231
+ console.log(chalk.yellow(`⊘ ${target}: no dir in this brand — skipped`));
232
+ });
233
+
234
+ if (selected.length === 0) {
235
+ console.error(chalk.red('✖ omega dev: nothing to boot (no selected target has a dir here)'));
236
+ process.exit(1);
237
+ }
238
+
239
+ console.log(chalk.bold(`🚀 omega dev — booting ${selected.join(' + ')} ${chalk.dim(`(${brandRoot})`)}`));
240
+ if (!options[PICKER_FLAG] && !options.all) {
241
+ console.log(chalk.dim(' default set is web + backend — `--target=`, `--all` pick it'));
242
+ }
243
+
244
+ // Dist freshness is checked ONCE, here, for every lane at once (#340). Each
245
+ // lane's CLI boot checks itself too — but a heal runs `npm run prepare`,
246
+ // which PURGES dist before recopying, and a framework bin opens by requiring
247
+ // its own `../dist/` entry. Unsynchronized, one lane's purge window is the
248
+ // sibling lane's require: the backend leg died MODULE_NOT_FOUND dispatching
249
+ // through the web package the web leg was mid-rebuild on. Swept first, every
250
+ // lane's own check is a no-op.
251
+ const hosts = [];
252
+ for (const target of selected) {
253
+ const entry = targets.find((item) => item.target === target);
254
+ const found = findTarget(entry.path);
255
+ if (found && found.kind === 'framework') {
256
+ hosts.push({ packageName: found.name, fromDir: found.dir });
257
+ }
258
+ }
259
+ const sweep = freshnessSweep({ hosts });
260
+ if (sweep.healed.length > 0) {
261
+ console.log(chalk.dim(` ✔ rebuilt ${sweep.healed.join(', ')} before booting — the legs start on a complete dist`));
262
+ }
263
+ if (sweep.staleLinked.length > 0) {
264
+ // The monorepo watch owns those dists (#281) — the sweep printed what is
265
+ // unbuilt and what to start; nothing boots on top of it.
266
+ throw new Error(`omega dev: ${sweep.staleLinked.map((entry) => entry.packageName).join(', ')} — see above; nothing booted`);
267
+ }
268
+ if (sweep.healFailed.length > 0) {
269
+ // The watch is down and the sweep's own rebuild broke (#398) — the sweep
270
+ // printed the prepare to run by hand; no leg boots on a dist nobody built.
271
+ throw new Error(`omega dev: ${sweep.healFailed.map((entry) => entry.packageName).join(', ')} — see above; nothing booted`);
272
+ }
273
+
274
+ // Boot opens with a full manage cycle (#44): the target watchers see only
275
+ // their own target, so brand-level sources — assets/logo/brandmark.svg, .env,
276
+ // certs — reach the targets ONLY through the service walk. Without this, a
277
+ // brand edit sits invisible until someone remembers to run `npm run manage`.
278
+ // A broken brand fails the boot instead of serving stale output.
279
+ // …and it never blocks on a human (#228): the boot walk runs headless, so
280
+ // console confirms, consent flows and secret pastes step aside into the run
281
+ // summary's ⚑ pending list instead of stalling the stack. `npm run manage`
282
+ // keeps the full interactive walk. The switch is restored before any leg
283
+ // spawns — the web dev server and the emulator ARE interactive surfaces.
284
+ //
285
+ // …and it walks only the BOOT LANE (#228): workspace + assets + disperse,
286
+ // the local redistribution the legs actually consume. The cloud services
287
+ // and the rebuild lane cost a minute-plus and nothing downstream of them
288
+ // reaches a dev leg, so they belong to `npm run manage` — or `--full` here.
289
+ const priorNonInteractive = process.env.OMEGA_NON_INTERACTIVE;
290
+ process.env.OMEGA_NON_INTERACTIVE = '1';
291
+ let report;
292
+ try {
293
+ report = await runManage(brandRoot, options.full ? {} : { lane: 'boot' });
294
+ } finally {
295
+ if (priorNonInteractive === undefined) {
296
+ delete process.env.OMEGA_NON_INTERACTIVE;
297
+ } else {
298
+ process.env.OMEGA_NON_INTERACTIVE = priorNonInteractive;
299
+ }
300
+ }
301
+ if (report.hasErrors) {
302
+ throw new Error('omega dev: the manage cycle reported errors — fix them (see the run summary above), then boot again');
303
+ }
304
+
305
+ if (!options.full) {
306
+ console.log(chalk.dim(' ⚑ boot ran the local lane only — `npm run manage` runs the full setup (or `omega dev --full`)'));
307
+ }
308
+
309
+ // The one-terminal rule covers FRAMEWORK edits too (#587). A brand whose
310
+ // @omega.js deps resolve into a monorepo checkout has no src→dist rebuild
311
+ // without that monorepo's watch, so this boot starts it as a session child —
312
+ // the same mechanism the website target's `--local` prelude uses, one
313
+ // implementation in devkit. Lock-aware: a watch already running is reused.
314
+ // AFTER the sweep on purpose: the sweep's verdict depends on whether a watch
315
+ // holds the lock (#281/#398), so starting one first would change the answer
316
+ // it just gave.
317
+ const linkedMonorepo = resolveLinkedMonorepo(brandRoot);
318
+ if (linkedMonorepo) {
319
+ const watch = startMonorepoWatch({ monorepoRoot: linkedMonorepo, logger: { log: (line) => console.log(chalk.dim(` ${line}`)) } });
320
+
321
+ // A watch's prepare rewrites every package's dist, and a target booting
322
+ // into that rewrite loads a half-written CLI (#670). The legs wait for the
323
+ // pass to land — a FRESH watch's initial one, and an ALREADY-RUNNING
324
+ // watch's, which is the branch a brand normally takes (Ian keeps the root
325
+ // `npm start` up) and the one that skipped the wait entirely (#622).
326
+ const outcome = await watch.ready;
327
+ if (outcome === 'ready') {
328
+ console.log(chalk.dim(` monorepo watch: ${watch.alreadyRunning ? 'nothing in flight' : 'initial prepare done'}`));
329
+ }
330
+ } else {
331
+ console.log(chalk.dim(' ⚑ frameworks come from the registry — no monorepo watch to run (a linked brand starts one here)'));
332
+ }
333
+
334
+ // The local certificate's root, resolved ONCE for every leg (#795): a leg
335
+ // that never speaks TLS ignores it, and this is verification rather than a
336
+ // bypass, so Node prints no warning. A shell-set value wins verbatim.
337
+ const caPem = process.env.NODE_EXTRA_CA_CERTS || mkcertCaRootPem();
338
+
339
+ const pad = Math.max(...selected.map((target) => target.length));
340
+ const children = [];
341
+ let shuttingDown = false;
342
+
343
+ // One deduper per stream, so the legs never collapse against each other.
344
+ // Terminal and file see the SAME collapsed stream: the tee patches this
345
+ // process' writers (#197), so there is one stream to dedup, not two.
346
+ const forward = (stream, log, name) => {
347
+ let buffer = '';
348
+ const deduper = createLineDeduper();
349
+ const emit = (lines) => lines.forEach((line) => log(`${chalk.dim(`[${name.padEnd(pad)}]`)} ${line}`));
350
+ stream.on('data', (chunk) => {
351
+ buffer += chunk.toString();
352
+ const lines = buffer.split('\n');
353
+ buffer = lines.pop();
354
+ lines.forEach((line) => emit(deduper.push(line)));
355
+ });
356
+ stream.on('end', () => emit(deduper.flush()));
357
+ };
358
+
359
+ for (const target of selected) {
360
+ const entry = targets.find((item) => item.target === target);
361
+ const leg = devLegFor(entry);
362
+ const node = resolveTargetNode(entry.path);
363
+ if (node?.error) {
364
+ console.log(chalk.yellow(` ⚠ ${target}: ${node.error} — using the inherited node`));
365
+ }
366
+
367
+ console.log(chalk.dim(` ${target.padEnd(pad)} → ${leg.join(' ')} in ${entry.dir}${node ? ` (node ${node.major})` : ''}`));
368
+
369
+ const child = spawn(leg[0], leg.slice(1), {
370
+ cwd: entry.path,
371
+ stdio: ['ignore', 'pipe', 'pipe'],
372
+ // Legs pipe their output — keep chalk colors when the parent's terminal
373
+ // has them (the log tee strips ANSI either way)
374
+ env: {
375
+ ...process.env,
376
+ ...nodeEnvFor(node),
377
+ FORCE_COLOR: process.stdout.isTTY ? '1' : process.env.FORCE_COLOR || '0',
378
+ ...(caPem ? { NODE_EXTRA_CA_CERTS: caPem } : {}),
379
+ },
380
+ // Own process group per leg (#690): a leg is a chain (npm run <leg> →
381
+ // the real server), and shutdown signals the GROUP — a same-group leg
382
+ // would get only npm killed, orphaning the emulator on its ports.
383
+ detached: true,
384
+ });
385
+ forward(child.stdout, console.log, target);
386
+ forward(child.stderr, console.error, target);
387
+ child.on('close', (code) => {
388
+ if (shuttingDown) return;
389
+ console.error(chalk.red(`✖ ${target} exited (code ${code}) — siblings stay up; Ctrl-C stops everything`));
390
+ });
391
+ children.push(child);
392
+ }
393
+
394
+ // The legs are detached (their own process groups), so the terminal's own
395
+ // Ctrl-C never reaches them — every escalation is this process' to deliver.
396
+ const forceKill = () => {
397
+ children.forEach((child) => {
398
+ try { process.kill(-child.pid, 'SIGKILL'); } catch { /* already gone */ }
399
+ });
400
+ process.exit(0);
401
+ };
402
+ const shutdown = () => {
403
+ if (shuttingDown) return forceKill(); // second Ctrl-C = force kill
404
+ shuttingDown = true;
405
+ console.log(chalk.dim('\n⏹ omega dev: stopping all targets… (Ctrl-C again to force kill)'));
406
+ children.forEach((child) => stopChild(child));
407
+ // Exit only when every leg is GONE: the backend leg's own teardown (the
408
+ // emulator group-kill + orphan sweep, seconds of work) logs through this
409
+ // process' pipes, and exiting under it cuts the sweep off mid-run (#690).
410
+ // The cap matches the 20s the journey/e2e harnesses allow that teardown,
411
+ // and expiry escalates so a wedged leg cannot keep its ports.
412
+ const cap = setTimeout(forceKill, 20000);
413
+ Promise.all(children.map((child) => new Promise((resolve) => {
414
+ if (child.exitCode !== null || child.signalCode) return resolve();
415
+ child.once('close', resolve);
416
+ }))).then(() => {
417
+ clearTimeout(cap);
418
+ process.exit(0);
419
+ });
420
+ };
421
+ // Every way this run is asked to stop takes the SAME teardown, off the ONE
422
+ // devkit list ([#629](https://github.com/Omega-JS-Stack/omega/issues/629)).
423
+ // SIGHUP was missing: a closed terminal killed the orchestrator outright and
424
+ // the legs, spawned DETACHED so a group signal cannot reach them, orphaned
425
+ // with the emulator tree behind them.
426
+ STOP_SIGNALS.forEach((signal) => process.on(signal, shutdown));
427
+
428
+ // Keep the orchestrator alive while any child runs
429
+ await new Promise(() => {});
430
+ };
431
+
432
+ module.exports.selectDevTargets = selectDevTargets;
433
+ module.exports.devLegFor = devLegFor;
434
+ module.exports.createLineDeduper = createLineDeduper;
435
+ module.exports.stopChild = stopChild;
436
+ module.exports.DEV_LEGS = DEV_LEGS;
437
+ module.exports.DEFAULT_TARGETS = DEFAULT_TARGETS;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `omega-manager devlog` — generate a commit-digest blog post from recent
3
+ * GitHub activity and publish it to the brand's website target.
4
+ *
5
+ * Flags: --brand=<id> (company workspaces; default = the single brand with
6
+ * devlog.enabled), --days=<n> overrides devlog.providers.ghostii.lookbackDays,
7
+ * --dry-run collects + generates only and writes a preview to .omega/devlog/
8
+ * instead of publishing.
9
+ */
10
+ const chalk = require('chalk').default;
11
+
12
+ const { runDevlog } = require('../devlog/index.js');
13
+
14
+ module.exports = async (options) => {
15
+ try {
16
+ await runDevlog(process.cwd(), {
17
+ brand: options.brand,
18
+ days: options.days,
19
+ dryRun: options.dryRun,
20
+ });
21
+ } catch (error) {
22
+ console.error(`${chalk.red('❌ Error')}${chalk.dim(`: ${error.message}`)}`);
23
+ process.exitCode = 1;
24
+ }
25
+ };