@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,569 @@
1
+ /**
2
+ * `omega update` core — the ONE dependency-freshness implementation behind
3
+ * every framework's update verb (npu-outdated semantics, Ian's node-power-user
4
+ * tool): per dependency report installed vs wanted vs latest, classify the
5
+ * jump (patch/minor/major), and QUARANTINE releases younger than --min-age
6
+ * days (default 7 — a brand-new publish may be a compromised one; hold it
7
+ * back unless explicitly forced). Report-only by default; --apply installs
8
+ * the non-quarantined, non-breaking set (majors need the explicit --major
9
+ * opt-in) through `npu install` when npu is on the machine, else plain
10
+ * `npm install` with a loud note.
11
+ *
12
+ * `file:`/`link:`/git specs have no registry story (the local era's linked
13
+ * @omega.js packages) — they're skipped with a dim note, never updated.
14
+ *
15
+ * Everything effectful is injectable (registry lookup, clock, exec) so the
16
+ * test suite never touches the network; the live path is the thin defaults.
17
+ */
18
+ const path = require('node:path');
19
+ const fs = require('node:fs');
20
+ const { execSync } = require('node:child_process');
21
+
22
+ const REGISTRY_BASE = 'https://registry.npmjs.org';
23
+ const DEFAULT_MIN_AGE_DAYS = 7;
24
+ const DAY_MS = 24 * 60 * 60 * 1000;
25
+
26
+ // Specs with no registry story: local links, git, tarball URLs, and the
27
+ // bare `owner/repo` GitHub shorthand (never a valid version range).
28
+ const NON_REGISTRY_SPEC = /^(file:|link:|workspace:|portal:|git\+|git:|github:|https?:)/;
29
+
30
+ /**
31
+ * Parse a semver-ish version string into comparable parts.
32
+ * @param {string} value - e.g. '1.2.3', 'v1.2.3', '1.2.3-beta.1'
33
+ * @returns {{ major: number, minor: number, patch: number, prerelease: string|null }|null}
34
+ */
35
+ function parseVersion(value) {
36
+ const match = String(value || '').trim().match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);
37
+ if (!match) return null;
38
+ return {
39
+ major: Number(match[1]),
40
+ minor: Number(match[2]),
41
+ patch: Number(match[3]),
42
+ prerelease: match[4] || null,
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Compare two version strings (-1 / 0 / 1). A prerelease sorts BEFORE its
48
+ * release triple; two prereleases compare lexically (enough for max-picking).
49
+ * @param {string} a
50
+ * @param {string} b
51
+ * @returns {number}
52
+ */
53
+ function compareVersions(a, b) {
54
+ const va = parseVersion(a);
55
+ const vb = parseVersion(b);
56
+ if (!va || !vb) return 0;
57
+
58
+ for (const key of ['major', 'minor', 'patch']) {
59
+ if (va[key] !== vb[key]) return va[key] < vb[key] ? -1 : 1;
60
+ }
61
+ if (va.prerelease === vb.prerelease) return 0;
62
+ if (va.prerelease === null) return 1;
63
+ if (vb.prerelease === null) return -1;
64
+ return va.prerelease < vb.prerelease ? -1 : 1;
65
+ }
66
+
67
+ /**
68
+ * Classify the jump between two versions.
69
+ * @param {string} from
70
+ * @param {string} to
71
+ * @returns {'major'|'minor'|'patch'|null} null when equal/unparseable
72
+ */
73
+ function classifyBump(from, to) {
74
+ const a = parseVersion(from);
75
+ const b = parseVersion(to);
76
+ if (!a || !b || compareVersions(from, to) === 0) return null;
77
+ if (a.major !== b.major) return 'major';
78
+ if (a.minor !== b.minor) return 'minor';
79
+ return 'patch';
80
+ }
81
+
82
+ /**
83
+ * Whether a spec points at the npm registry at all.
84
+ * @param {string} spec - package.json dependency value
85
+ * @returns {boolean}
86
+ */
87
+ function isRegistrySpec(spec) {
88
+ const value = String(spec || '').trim();
89
+ if (NON_REGISTRY_SPEC.test(value)) return false;
90
+ // GitHub shorthand: owner/repo — a '/' never appears in a version range
91
+ if (value.includes('/')) return false;
92
+ return true;
93
+ }
94
+
95
+ /**
96
+ * Extract the base version from a range spec ('^1.2.3' → '1.2.3').
97
+ * @param {string} spec
98
+ * @returns {string|null} null when the spec has no single base ('*', 'latest', '1.x')
99
+ */
100
+ function cleanSpec(spec) {
101
+ const match = String(spec || '').trim().match(/^[\^~=]?\s*v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/);
102
+ return match ? match[1] : null;
103
+ }
104
+
105
+ /**
106
+ * Highest stable version satisfying a range spec — npm-outdated's "wanted".
107
+ * Understands the specs this ecosystem actually writes: exact, ^, ~, >=,
108
+ * x-ranges ('1.2.x', '1.x', '1'), and '*'/''/'latest'. Anything else → null.
109
+ * @param {string} spec
110
+ * @param {string[]} versions - all published versions
111
+ * @returns {string|null}
112
+ */
113
+ function resolveWanted(spec, versions) {
114
+ const value = String(spec || '').trim();
115
+ const stable = versions.filter((v) => {
116
+ const parsed = parseVersion(v);
117
+ return parsed && !parsed.prerelease;
118
+ }).sort(compareVersions);
119
+ const max = (list) => (list.length > 0 ? list[list.length - 1] : null);
120
+
121
+ if (value === '*' || value === '' || value === 'latest') return max(stable);
122
+
123
+ const base = cleanSpec(value);
124
+ if (base) {
125
+ const parsed = parseVersion(base);
126
+ const atLeast = stable.filter((v) => compareVersions(v, base) >= 0);
127
+
128
+ if (value.startsWith('^')) {
129
+ // Caret: same major; 0.x pins the minor; 0.0.x pins the patch
130
+ return max(atLeast.filter((v) => {
131
+ const candidate = parseVersion(v);
132
+ if (candidate.major !== parsed.major) return false;
133
+ if (parsed.major === 0 && candidate.minor !== parsed.minor) return false;
134
+ if (parsed.major === 0 && parsed.minor === 0 && candidate.patch !== parsed.patch) return false;
135
+ return true;
136
+ }));
137
+ }
138
+ if (value.startsWith('~')) {
139
+ return max(atLeast.filter((v) => {
140
+ const candidate = parseVersion(v);
141
+ return candidate.major === parsed.major && candidate.minor === parsed.minor;
142
+ }));
143
+ }
144
+ // Exact (with or without '=')
145
+ return versions.includes(base) ? base : null;
146
+ }
147
+
148
+ if (value.startsWith('>=')) {
149
+ const floor = cleanSpec(value.slice(2));
150
+ return floor ? max(stable.filter((v) => compareVersions(v, floor) >= 0)) : null;
151
+ }
152
+
153
+ // x-ranges: '1', '1.x', '1.2', '1.2.x', '1.2.*' ('1.2.3' exact was handled above)
154
+ const xMatch = value.match(/^(\d+)(?:\.(\d+|[x*]))?(?:\.[x*])?$/);
155
+ if (xMatch) {
156
+ const major = Number(xMatch[1]);
157
+ const minor = xMatch[2] === undefined || /[x*]/.test(xMatch[2]) ? null : Number(xMatch[2]);
158
+ return max(stable.filter((v) => {
159
+ const candidate = parseVersion(v);
160
+ return candidate.major === major && (minor === null || candidate.minor === minor);
161
+ }));
162
+ }
163
+
164
+ return null;
165
+ }
166
+
167
+ /**
168
+ * Highest stable version within a bump tier of `current` — npu's
169
+ * patch/minor/latest targets.
170
+ * @param {string[]} versions
171
+ * @param {string} current
172
+ * @param {'patch'|'minor'|'latest'} tier
173
+ * @returns {string|null}
174
+ */
175
+ function highestWithin(versions, current, tier) {
176
+ const parsed = parseVersion(current);
177
+ if (!parsed) return null;
178
+
179
+ const candidates = versions.filter((v) => {
180
+ const candidate = parseVersion(v);
181
+ if (!candidate || candidate.prerelease) return false;
182
+ if (compareVersions(v, current) < 0) return false;
183
+ if (tier === 'patch') return candidate.major === parsed.major && candidate.minor === parsed.minor;
184
+ if (tier === 'minor') return candidate.major === parsed.major;
185
+ return true;
186
+ }).sort(compareVersions);
187
+
188
+ return candidates.length > 0 ? candidates[candidates.length - 1] : null;
189
+ }
190
+
191
+ /**
192
+ * Find a dependency's physically installed version — nearest node_modules
193
+ * copy walking UP from dir (npm hoists to the brand root in brand monorepos).
194
+ * @param {string} name - package name
195
+ * @param {string} dir - starting directory
196
+ * @returns {string|null}
197
+ */
198
+ function findInstalledVersion(name, dir) {
199
+ let current = path.resolve(dir);
200
+ for (;;) {
201
+ const manifest = path.join(current, 'node_modules', ...name.split('/'), 'package.json');
202
+ if (fs.existsSync(manifest)) {
203
+ try {
204
+ return JSON.parse(fs.readFileSync(manifest, 'utf8')).version || null;
205
+ } catch (e) {
206
+ return null;
207
+ }
208
+ }
209
+ const parent = path.dirname(current);
210
+ if (parent === current) return null;
211
+ current = parent;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Live registry lookup — full packument (the abbreviated form has no publish
217
+ * times). The ONE network call of the verb; tests inject a fixture instead.
218
+ * @param {string} name - package name
219
+ * @param {object} [options]
220
+ * @param {function} [options.fetchFn] - injectable fetch
221
+ * @param {string} [options.registryUrl] - registry base URL
222
+ * @returns {Promise<{ latest: string|null, versions: string[], time: object }>}
223
+ */
224
+ async function fetchPackument(name, options = {}) {
225
+ const fetchFn = options.fetchFn || fetch;
226
+ const base = options.registryUrl || REGISTRY_BASE;
227
+ const response = await fetchFn(`${base}/${name.replace('/', '%2F')}`, {
228
+ headers: { Accept: 'application/json' },
229
+ });
230
+ if (response.status === 404) {
231
+ // Zero publishes so far for @omega.js/* (HARD RULE 2) — a 404 is expected
232
+ // in-monorepo, so say what it means instead of a bare status code
233
+ throw new Error('not on the registry (unpublished?)');
234
+ }
235
+ if (!response.ok) {
236
+ throw new Error(`registry ${response.status} for ${name}`);
237
+ }
238
+ const body = await response.json();
239
+ return {
240
+ latest: body['dist-tags']?.latest || null,
241
+ versions: Object.keys(body.versions || {}),
242
+ time: body.time || {},
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Build the full update report for one target's package.json.
248
+ * @param {object} options
249
+ * @param {string} options.dir - target directory (package.json + node_modules climb)
250
+ * @param {function} options.lookup - async (name) => { latest, versions, time }
251
+ * @param {number} [options.now] - clock (ms epoch; injectable for tests)
252
+ * @param {number} [options.minAge] - quarantine threshold in days (default 7; 0 disables)
253
+ * @returns {Promise<{ project: string, rows: object[], locals: object[] }>}
254
+ */
255
+ async function buildUpdateReport(options) {
256
+ const dir = options.dir;
257
+ const now = options.now ?? Date.now();
258
+ const minAge = options.minAge ?? DEFAULT_MIN_AGE_DAYS;
259
+
260
+ const manifestPath = path.join(dir, 'package.json');
261
+ if (!fs.existsSync(manifestPath)) {
262
+ throw new Error(`No package.json in ${dir}`);
263
+ }
264
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
265
+
266
+ // `only` narrows the manifest to a named set — the brand-root shell rides
267
+ // the fan-out for its @omega.js/manager pin alone (#794), and a brand's own
268
+ // root tooling is none of that leg's business.
269
+ const only = Array.isArray(options.only) ? new Set(options.only) : null;
270
+ const pick = (deps) => (only ? Object.fromEntries(Object.entries(deps).filter(([name]) => only.has(name))) : deps);
271
+
272
+ const groups = [
273
+ ['prod', pick(manifest.dependencies || {})],
274
+ ['dev', pick(manifest.devDependencies || {})],
275
+ ];
276
+
277
+ const locals = [];
278
+ const rows = [];
279
+
280
+ await Promise.all(groups.flatMap(([group, deps]) => Object.entries(deps).map(async ([name, spec]) => {
281
+ if (!isRegistrySpec(spec)) {
282
+ locals.push({ name, group, spec });
283
+ return;
284
+ }
285
+
286
+ const installed = findInstalledVersion(name, dir);
287
+ const current = cleanSpec(spec) || installed;
288
+
289
+ const row = {
290
+ name, group, spec, current, installed,
291
+ wanted: null, latest: null, patchTarget: null, minorTarget: null,
292
+ bump: null, publishedAt: null, ageDays: null, quarantined: false, error: null,
293
+ };
294
+ rows.push(row);
295
+
296
+ let packument;
297
+ try {
298
+ packument = await options.lookup(name);
299
+ } catch (e) {
300
+ row.error = e.message;
301
+ return;
302
+ }
303
+
304
+ row.wanted = resolveWanted(spec, packument.versions);
305
+ row.latest = packument.latest
306
+ || resolveWanted('*', packument.versions);
307
+ if (current) {
308
+ row.patchTarget = highestWithin(packument.versions, current, 'patch');
309
+ row.minorTarget = highestWithin(packument.versions, current, 'minor');
310
+ row.bump = row.latest ? classifyBump(current, row.latest) : null;
311
+ }
312
+ row.time = packument.time;
313
+
314
+ // Quarantine display: how fresh is the latest release?
315
+ const publishedAt = packument.time?.[row.latest];
316
+ if (publishedAt) {
317
+ row.publishedAt = new Date(publishedAt);
318
+ row.ageDays = Math.floor((now - row.publishedAt.getTime()) / DAY_MS);
319
+ row.quarantined = minAge > 0 && row.ageDays < minAge && installed !== row.latest;
320
+ }
321
+ })));
322
+
323
+ // Only rows needing attention, prod before dev, alpha within group
324
+ const rank = { prod: 0, dev: 1 };
325
+ const attention = rows
326
+ .filter((row) => row.error || (row.latest && row.latest !== row.current) || (row.installed && row.current && row.installed !== row.current))
327
+ .sort((a, b) => (rank[a.group] - rank[b.group]) || a.name.localeCompare(b.name));
328
+
329
+ locals.sort((a, b) => a.name.localeCompare(b.name));
330
+
331
+ return { project: manifest.name || path.basename(dir), rows: attention, locals };
332
+ }
333
+
334
+ /**
335
+ * Pick the updates an --apply run installs. Default tier is MINOR (highest
336
+ * same-major — npu's non-breaking lane); --major unlocks latest. A target
337
+ * published < minAge days ago is HELD (quarantine) unless already installed.
338
+ * @param {object[]} rows - buildUpdateReport rows
339
+ * @param {object} [options]
340
+ * @param {boolean} [options.major] - allow breaking jumps to latest
341
+ * @param {number} [options.minAge] - quarantine threshold in days (0 disables)
342
+ * @param {number} [options.now] - clock (injectable)
343
+ * @returns {{ updates: object[], quarantined: object[], majorsHeld: object[] }}
344
+ */
345
+ function selectUpdates(rows, options = {}) {
346
+ const minAge = options.minAge ?? DEFAULT_MIN_AGE_DAYS;
347
+ const now = options.now ?? Date.now();
348
+
349
+ const updates = [];
350
+ const quarantined = [];
351
+ const majorsHeld = [];
352
+
353
+ for (const row of rows) {
354
+ if (row.error || !row.current) continue;
355
+
356
+ const target = options.major ? row.latest : row.minorTarget;
357
+ if (!target || compareVersions(target, row.current) <= 0) {
358
+ // Nothing applicable in-tier; note the held major so the human sees it
359
+ if (!options.major && row.bump === 'major' && row.latest !== row.installed) {
360
+ majorsHeld.push({ name: row.name, from: row.current, to: row.latest });
361
+ }
362
+ continue;
363
+ }
364
+
365
+ // Quarantine the TARGET version by its own publish age
366
+ const publishedAt = row.time?.[target];
367
+ const ageDays = publishedAt ? Math.floor((now - new Date(publishedAt).getTime()) / DAY_MS) : null;
368
+ if (minAge > 0 && ageDays !== null && ageDays < minAge && row.installed !== target) {
369
+ quarantined.push({ name: row.name, from: row.current, to: target, ageDays });
370
+ continue;
371
+ }
372
+
373
+ updates.push({ name: row.name, group: row.group, from: row.current, to: target, bump: classifyBump(row.current, target) });
374
+
375
+ if (!options.major && row.bump === 'major' && row.latest !== target) {
376
+ majorsHeld.push({ name: row.name, from: row.current, to: row.latest });
377
+ }
378
+ }
379
+
380
+ return { updates, quarantined, majorsHeld };
381
+ }
382
+
383
+ /**
384
+ * Whether npu (node-power-user — the Socket-firewalled npm wrapper) exists
385
+ * on this machine.
386
+ * @param {object} [options]
387
+ * @param {function} [options.execFn] - injectable exec
388
+ * @returns {boolean}
389
+ */
390
+ function detectNpu(options = {}) {
391
+ const execFn = options.execFn || ((cmd, opts) => execSync(cmd, opts));
392
+ try {
393
+ execFn('npu --version', { stdio: ['ignore', 'pipe', 'ignore'] });
394
+ return true;
395
+ } catch (e) {
396
+ return false;
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Build the install command(s) for a selected update set — one per dep group
402
+ * (npm relocates a dev dep to dependencies without --save-dev). Installs run
403
+ * through `npu install` when npu exists (Socket supply-chain firewall);
404
+ * otherwise plain `npm install` (the caller warns loudly).
405
+ *
406
+ * The @omega.js family rides its own command per group, with `--save-exact`
407
+ * (#794): npm's default save-prefix writes `^<version>`, so the one verb that
408
+ * is ALLOWED to move a brand would have un-pinned the family it just moved.
409
+ * Everything else keeps npm's default prefix — the pin is the family's rule,
410
+ * not a rule for the whole dependency tree.
411
+ * @param {object[]} updates - selectUpdates().updates
412
+ * @param {object} options
413
+ * @param {boolean} options.hasNpu
414
+ * @returns {Array<{ command: string, group: string }>}
415
+ */
416
+ function buildInstallCommands(updates, options) {
417
+ const bin = options.hasNpu ? 'npu install' : 'npm install';
418
+ const commands = [];
419
+
420
+ for (const [group, flag] of [['prod', ''], ['dev', ' --save-dev']]) {
421
+ const inGroup = updates.filter((update) => update.group === group);
422
+
423
+ for (const [family, extra] of [[false, ''], [true, ' --save-exact']]) {
424
+ const specs = inGroup
425
+ .filter((update) => update.name.startsWith('@omega.js/') === family)
426
+ .map((update) => `${update.name}@${update.to}`);
427
+ if (specs.length > 0) {
428
+ commands.push({ command: `${bin} ${specs.join(' ')}${flag}${extra}`, group });
429
+ }
430
+ }
431
+ }
432
+
433
+ return commands;
434
+ }
435
+
436
+ /**
437
+ * Render the report as plain padded-table lines (framework wrappers print
438
+ * them through their own logger; no color dependency in the shared core).
439
+ * @param {{ project: string, rows: object[], locals: object[] }} report
440
+ * @param {object} [options]
441
+ * @param {number} [options.minAge]
442
+ * @returns {string[]}
443
+ */
444
+ function formatReport(report, options = {}) {
445
+ const minAge = options.minAge ?? DEFAULT_MIN_AGE_DAYS;
446
+ const lines = [];
447
+
448
+ if (report.rows.length === 0) {
449
+ lines.push('All registry dependencies are up to date.');
450
+ } else {
451
+ const header = ['Package', 'Group', 'Current', 'Installed', 'Wanted', 'Latest', 'Bump', 'Released', 'Status'];
452
+ const body = report.rows.map((row) => {
453
+ const released = row.publishedAt
454
+ ? `${row.publishedAt.toISOString().split('T')[0]} (${row.ageDays}d)`
455
+ : '-';
456
+ const status = row.error ? `lookup failed: ${row.error}`
457
+ : row.quarantined ? 'QUARANTINED'
458
+ : '';
459
+ return [
460
+ row.name, row.group, row.current || '-', row.installed || '-',
461
+ row.wanted || '-', row.latest || '-', row.bump || '-', released, status,
462
+ ];
463
+ });
464
+
465
+ const widths = header.map((cell, index) => Math.max(cell.length, ...body.map((cells) => String(cells[index]).length)));
466
+ const render = (cells) => cells.map((cell, index) => String(cell).padEnd(widths[index])).join(' ').trimEnd();
467
+ lines.push(render(header));
468
+ lines.push(widths.map((width) => '-'.repeat(width)).join(' '));
469
+ for (const cells of body) lines.push(render(cells));
470
+
471
+ if (report.rows.some((row) => row.quarantined)) {
472
+ lines.push(`QUARANTINED = latest published < ${minAge} days ago (held from --apply; --min-age 0 or --force-fresh overrides)`);
473
+ }
474
+ if (report.rows.some((row) => row.bump === 'major')) {
475
+ lines.push('major = breaking — never auto-applied (explicit --major opt-in)');
476
+ }
477
+ }
478
+
479
+ for (const local of report.locals) {
480
+ lines.push(`skipped ${local.name} (${local.spec}) — local spec, no registry story`);
481
+ }
482
+
483
+ return lines;
484
+ }
485
+
486
+ /**
487
+ * The one verb body every wrapper calls: report (default), then apply when
488
+ * asked. Flags mirror npu: --apply, --major, --min-age N (default 7, 0
489
+ * disables), --force-fresh (alias for --min-age 0).
490
+ * @param {object} [options]
491
+ * @param {string} [options.dir] - target directory (default cwd)
492
+ * @param {string[]} [options.only] - check just these package names (#794)
493
+ * @param {boolean} [options.apply] - install the selected set
494
+ * @param {boolean} [options.major] - allow breaking jumps (with --apply)
495
+ * @param {number} [options.minAge] - quarantine threshold in days
496
+ * @param {boolean} [options.forceFresh] - disable the age quarantine
497
+ * @param {object} [options.logger] - logger with log/warn (default console)
498
+ * @param {function} [options.lookup] - injectable registry lookup (tests)
499
+ * @param {function} [options.execFn] - injectable exec (tests)
500
+ * @param {number} [options.now] - injectable clock (tests)
501
+ * @param {boolean} [options.hasNpu] - injectable npu detection (tests)
502
+ * @returns {Promise<{ report: object, selection: object|null, commands: object[] }>}
503
+ */
504
+ async function runUpdate(options = {}) {
505
+ const dir = options.dir || process.cwd();
506
+ const logger = options.logger || console;
507
+ const now = options.now ?? Date.now();
508
+ const minAge = options.forceFresh ? 0 : Number(options.minAge ?? DEFAULT_MIN_AGE_DAYS);
509
+ const lookup = options.lookup || ((name) => fetchPackument(name));
510
+
511
+ const report = await buildUpdateReport({ dir, lookup, now, minAge, only: options.only });
512
+ logger.log(`Dependency report for ${report.project}:`);
513
+ for (const line of formatReport(report, { minAge })) logger.log(line);
514
+
515
+ if (!options.apply) {
516
+ if (report.rows.length > 0) {
517
+ logger.log('Report only — `omega update --apply` installs the non-quarantined, non-breaking set (--major for breaking).');
518
+ }
519
+ return { report, selection: null, commands: [] };
520
+ }
521
+
522
+ const selection = selectUpdates(report.rows, { major: options.major, minAge, now });
523
+
524
+ for (const held of selection.quarantined) {
525
+ logger.warn(`held ${held.name}@${held.to} — published ${held.ageDays}d ago (< ${minAge}d quarantine)`);
526
+ }
527
+ for (const held of selection.majorsHeld) {
528
+ logger.warn(`held ${held.name} ${held.from} → ${held.to} — major (breaking); re-run with --major to include`);
529
+ }
530
+
531
+ if (selection.updates.length === 0) {
532
+ logger.log('Nothing to apply.');
533
+ return { report, selection, commands: [] };
534
+ }
535
+
536
+ const hasNpu = options.hasNpu ?? detectNpu({ execFn: options.execFn });
537
+ if (!hasNpu) {
538
+ logger.warn('npu (node-power-user) is NOT on this machine — installing via plain `npm install`, WITHOUT the Socket supply-chain firewall.');
539
+ }
540
+
541
+ const commands = buildInstallCommands(selection.updates, { hasNpu });
542
+ const execFn = options.execFn || ((cmd, opts) => execSync(cmd, opts));
543
+ for (const entry of commands) {
544
+ logger.log(`Running: ${entry.command}`);
545
+ execFn(entry.command, { cwd: dir, stdio: 'inherit' });
546
+ }
547
+
548
+ logger.log(`Applied ${selection.updates.length} update(s).`);
549
+ return { report, selection, commands };
550
+ }
551
+
552
+ module.exports = {
553
+ DEFAULT_MIN_AGE_DAYS,
554
+ parseVersion,
555
+ compareVersions,
556
+ classifyBump,
557
+ isRegistrySpec,
558
+ cleanSpec,
559
+ resolveWanted,
560
+ highestWithin,
561
+ findInstalledVersion,
562
+ fetchPackument,
563
+ buildUpdateReport,
564
+ selectUpdates,
565
+ detectNpu,
566
+ buildInstallCommands,
567
+ formatReport,
568
+ runUpdate,
569
+ };