@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,139 @@
1
+ # OMEGA — the Claude plugin
2
+
3
+ OMEGA's knowledge for Claude sessions, shipped as a Claude Code plugin from the monorepo that holds the code it describes. Install it and any session working on an OMEGA project gets the current conventions, without the knowledge living in any one developer's personal harness.
4
+
5
+ ## Why it lives here
6
+
7
+ A skill kept anywhere else is a hand-maintained pointer into a repo that moves on its own schedule — nothing makes the two agree, and nothing notices when they stop. A skill that ships beside the code is version-matched by construction, and it is the same commit that changes the framework and the sentence describing it.
8
+
9
+ ## Install
10
+
11
+ In this monorepo, install is automatic: the committed `.claude/settings.json` registers the repo-root marketplace (`.claude-plugin/marketplace.json`, relative path) and enables `omega@omega` — Claude Code asks one trust question on first open, then the plugin loads every session. For any other checkout, the manual form:
12
+
13
+ ```sh
14
+ claude plugin marketplace add <path-to-this-monorepo-checkout>
15
+ claude plugin install omega@omega
16
+ ```
17
+
18
+ Plugins load at startup, so a new (or restarted) session — or `/reload-plugins` — is what puts a change into effect. Installed plugins are cache copies; live plugin development runs `claude --plugin-dir ./agent-plugins/claude` instead.
19
+
20
+ A marketplace added from a local path is read in place — nothing is cloned, so living in a monorepo costs a local install nothing. Installing from GitHub is what makes repo size matter, and the marketplace entry switches to the `git-subdir` source for that: a url plus `"path": "agent-plugins/claude"`, which Claude Code fetches with a sparse partial clone rather than pulling the whole monorepo. Make that change when the plugin is first installed from a remote, not before — the relative `./agent-plugins/claude` source is the right one while every install is local.
21
+
22
+ ## Layout
23
+
24
+ ```
25
+ agent-plugins/
26
+ └── claude/
27
+ ├── .claude-plugin/plugin.json the manifest
28
+ ├── .mcp.json the one MCP declaration — the @omega.js/mcp-router endpoint
29
+ ├── README.md this file
30
+ ├── hooks/ hooks.json, the inject/gate/guard/shape/quality hooks, and lib/ (the shared scope guard, skill map, and gate-marker naming)
31
+ └── skills/ the skills, one directory each (see skills/README.md)
32
+ ```
33
+
34
+ `agent-plugins/` is the parent for every coding agent OMEGA ships knowledge to, and `claude/` is the Claude Code one. A second provider gets a sibling directory rather than a rearrangement.
35
+
36
+ Structure is validated by `scripts/agent-plugins.test.js` at the monorepo root, which runs in `npm test`.
37
+
38
+ ## The inject hook
39
+
40
+ The plugin carries the mechanism that loads its own skills. `hooks/inject/run.sh` runs on every prompt (`UserPromptSubmit`), reads the project's `package.json` — the working directory's own, else the nearest one up to the git root — and asks the session to invoke the skill for the framework it finds:
41
+
42
+ | package | skill |
43
+ |---|---|
44
+ | `@omega.js/web` | `omega:web` |
45
+ | `@omega.js/backend` | `omega:backend` |
46
+ | `@omega.js/desktop` | `omega:desktop` |
47
+ | `@omega.js/extension` | `omega:extension` |
48
+ | `@omega.js/manager` | `omega:manager` |
49
+ | `@omega.js/client` | `omega:client` — the project's own `name` only |
50
+ | `omega` (the monorepo root) | `omega:main` — the project's own `name` only |
51
+
52
+ Every row also matches the manifest's own `name`, which is what covers working inside a `packages/<pkg>` directory in this monorepo. `@omega.js/client` is the exception the other way: the runtime is embedded by web, desktop, and extension, so a dependency on it says nothing about what the session is working on — only being the package asks for its skill.
53
+
54
+ **At a brand root, the nearest manifest is not the answer.** It carries `@omega.js/manager` alone, so a session at a brand root used to hear about the manager and nothing about the targets it was there to build. The hook now recognizes a brand — a directory carrying `config/omega.json5`, or one whose manifest depends on `@omega.js/manager`, found by walking up to the git root — and reads the level below it: `config/omega.json5`'s `targets` keys AND every `targets/*/package.json` (plus the `functions/package.json` a Firebase backend keeps its framework in). The whole set comes back at once: `omega:main` and `omega:manager` always, plus one `omega:<framework>` per target. A target no framework owns (`type: 'custom'`) and `mobile` (parked) map to nothing.
55
+
56
+ A brand injection also names the framework map — the brand `AGENTS.md` import line, `node_modules/@omega.js/AGENTS.md` — as required reading BEFORE the first edit, which is what the gate hook below enforces.
57
+
58
+ Each skill is asked for once per session per SKILL (a marker file under `TMPDIR`, keyed on the session id), so a target that appears mid-session still gets its own line while the skills already asked for stay quiet. The hook fails open — no `package.json`, unparseable JSON, an unreadable config, no `jq`, and it exits silently without touching the prompt. Behavior is covered by the inject cases in `scripts/agent-plugins.test.js`, which run the script directly against fixture projects.
59
+
60
+ ## The gate hook
61
+
62
+ Injecting a line only SUGGESTS a skill, and a session that skipped the line built a whole `targets/website` app without ever loading `omega:web` — hand-rolled markup, and a documented validator rule filed as a framework bug. So the skills are enforced. `hooks/gate/run.sh` serves two events from one script — the surface question has ONE answer — and refuses a write to a surface whose skill was never invoked:
63
+
64
+ | Surface written or edited | Gated on |
65
+ |---|---|
66
+ | `<brand>/targets/<t>/**` | that target's framework skill, read from its own `package.json` (a custom target gates on nothing) |
67
+ | `<brand>/config/omega.json5` | `omega:manager` — the file the manage walk reconciles |
68
+ | `<monorepo>/packages/<pkg>/**`, where the manifest IS `@omega.js/<pkg>` | that package's skill: `omega:web`, `omega:backend`, `omega:desktop`, `omega:extension`, `omega:client`, `omega:manager` |
69
+ | a WEB theme surface, on top of the row above: the packaged `themes/**`, a website target's `themes/**` or `src/themes/**`, its `src/_sections/**` and `src/_components/**` (one override lane), and its `src/assets/css/main.scss` | `omega:theme` IN ADDITION to that surface's own skill — the cascade has its own contract, and it is a web mechanism, so a `themes/` dir in a backend target is not one |
70
+
71
+ A surface can therefore answer with MORE than one skill, and the gate refuses until EVERY one of them has been invoked — a half-loaded theme edit is refused naming only what is still missing. The inject hook wires none of this: it answers "what does this PROJECT run?" from manifest deps and config target keys, never from a path, so a skill that fires on a surface rather than a package has nothing to add there.
72
+
73
+ Everything else is free: docs, scripts, the plugin's own files, a brand's root files, a `packages/` directory in somebody else's repo, and every internal package with no skill (`devkit`, `config`, `account`, `analytics`, `monitoring`, `template-kit`, `mcp-router`). Read-only tools are never in scope — the matcher is `Write|Edit`, so reading the code before loading the skill is exactly right.
74
+
75
+ On `PostToolUse` (matcher `Skill`) the hook records every skill the session invoked, in either spelling — the namespaced `omega:web` or the bare `web` the plugin namespaces. On `PreToolUse` (`Write|Edit`) an unrecorded surface exits 2 with the skill to invoke, so the model is told what to do rather than what it did wrong. Markers live under `TMPDIR/omega-gate`, keyed on the session id.
76
+
77
+ **Two lanes record the read, and only two.** In the main chat the agent has a Skill tool, so invoking `omega:web` records itself and nothing else is needed. An agent with NO Skill tool (the workkit worker class writes its files through Bash, which a `Write|Edit` matcher never sees) reads the guide its brief names, then runs the ONE sanctioned command: `hooks/gate/mark.sh omega:web` (either spelling the Skill event takes, `omega:web` or bare `web`), which writes the same marker through the same lib (`hooks/lib/omega-gate.sh`) and prints the path it wrote. The script lives at `agent-plugins/claude/hooks/gate/mark.sh` in this monorepo and at `node_modules/@omega.js/manager/claude-plugin/hooks/gate/mark.sh` in a brand on a published install. It takes the session id from `--session <id>` when given (explicit beats ambient), else from `$CLAUDE_SESSION_ID`, else `$CLAUDE_CODE_SESSION_ID`; with none it exits 1 with its usage. Writing a marker by hand, or running `mark.sh` before reading the guide, is a process breach rather than a third lane: the gate is a reading contract, not a lock to pick, and the verifier checks that the worker's report names the guide it read. The gate itself stays a MAIN-CHAT guard on purpose: it does not try to match the paths a heredoc, `sed`, or a python one-liner targets, because best-effort path parsing misses more than it catches ([#760](https://github.com/Omega-JS-Stack/omega/issues/760)).
78
+
79
+ The gate and the inject hook read ONE table: `hooks/lib/omega-skills.sh`, which owns the framework → skill map, the brand walk, the JSON5 target-key scan, and the surface lookup — so the hook that ASKS for a skill and the hook that REFUSES an edit without it agree on the map itself. They can still ask different questions of it: inject reads the config's target keys too, while the gate resolves a target from its own manifest alone, so a target declared in `omega.json5` before its directory exists is asked for and not gated. That is fail-open by design — the gate refuses only what it can positively identify. Fail-open throughout: no `jq`, an unreadable manifest or config, an unusable marker directory, and the gate lets the write through. Covered by the gate cases in `scripts/agent-plugins.test.js`.
80
+
81
+ ## The guard hook
82
+
83
+ The gate makes a session READ the framework docs; the guard makes it act on them. `hooks/guard/run.sh` runs on `PreToolUse` (`Write|Edit`) beside the gate and refuses an edit to a framework-owned file inside a CONSUMER BRAND — the upstream-first rule as a mechanism, because "a framework hole gets a framework issue, never a consumer patch" had to be restated three times in one migration session before the hand-written rules and templates stopped landing ([#452](https://github.com/Omega-JS-Stack/omega/issues/452)). Two classes:
84
+
85
+ | Class | What it catches | Escape |
86
+ |---|---|---|
87
+ | 1. Generated or vendored | any path under `node_modules/`, any `dist/` tree, a file whose first 20 lines say `GENERATED FILE` + `DO NOT EDIT` or `Generated by @omega.js/`, and `database.rules.json` (the OMEGA-managed rules block) | none — the message names the real source to edit instead (the config, the build source, the brand's own `firestore.rules`) |
88
+ | 2. Shadow copies | a brand file whose path mirrors a file the installed framework ships through its OVERRIDE LAYER | `omega:consumer-override: <reason>` in the file's first 5 lines, in any comment syntax (`//`, `#`, `<!--`, `{#`, `/*`), or `OMEGA_CONSUMER_OVERRIDE=1` for the session |
89
+
90
+ The shadow map is read from the LIVE install (`<brand>/node_modules/@omega.js/<framework>/`), never a hardcoded list, so the knowledge matches the version the brand actually runs. ONE table in the hook holds the lookup roots — `<framework>|<consumer prefix, relative to the target root>|<framework root>`, one row per real override-layer root:
91
+
92
+ | Framework | Consumer prefix | Framework roots |
93
+ |---|---|---|
94
+ | `web` | `src/_layouts/` | `core/_layouts/`, `themes/*/_layouts/` |
95
+ | `web` | `src/_includes/` | `core/_includes/`, `themes/*/_includes/` |
96
+ | `web` | `src/_sections/` | `themes/*/_sections/` |
97
+ | `web` | `src/_components/` | `themes/*/_components/` |
98
+ | `web` | `src/assets/css/` | `core/css/`, `themes/*/css/` |
99
+ | `backend` | `src/routes/` | `src/manager/routes/` |
100
+ | `backend` | `src/schemas/` | `src/manager/schemas/` |
101
+ | `backend` | (the target root) | `templates/` |
102
+
103
+ The web rows mirror `packages/web/src/overrides.js` `overrideLanes()` (sections, includes, css) plus the engine's layered `_layouts`: the MECHANISM lanes, where first-layer-wins resolution means a consumer file genuinely takes the framework's place. Sections sit in the theme layers only, because core ships none. The backend rows are the two lanes that really replace a framework file BY NAME — `packages/backend/src/manager/index.js` resolves a consumer route or schema of the same name and method over the framework's — plus the framework half of the rules that ships in `templates/`.
104
+
105
+ **Pages are never guarded.** `src/pages/` is CONTENT: the designed place for a brand to write its own homepage, about page and pricing page, whether or not the framework ships a default of that name. There is no `defaults/` row and no page row. **There is no js row either**, because page and layout modules are a UNION ([#624](https://github.com/Omega-JS-Stack/omega/issues/624) — every layer's file runs, in layer order) rather than a shadow, so a brand's `src/assets/js/pages/blog.js` replaces nothing.
106
+
107
+ Two exemption sets, both by name and both traceable to a document:
108
+
109
+ - **The consumer's own entry files**, which the docs hand to the brand outright: `src/assets/css/main.scss` ([docs/shared/theming.md](../../docs/shared/theming.md) § Consumer customization, tier 1), plus `src/assets/js/main.js` and `src/assets/js/first-paint.js` ([docs/web/index.md](../../docs/web/index.md) — the one REPLACE-with-extend lane, where a consumer file reaches the framework's through `omega:main`). Owning one of those IS the documented recipe, so the guard never asks about it.
110
+ - **The backend seeds** the target checks (`omega test`) write once and the brand owns from then on, each healed by a check in `@omega.js/backend`'s `src/cli/commands/setup-tests/`: `firestore.rules`, `storage.rules`, `firebase.json`, `firestore.indexes.json`, `remoteconfig.template.json`, `public/`, `config/`, and `storage-lifecycle-*.json`.
111
+
112
+ **Desktop and extension have no rows at all**, and that is a finding rather than an omission: neither framework ships an override layer. Their `src/defaults/` tree is scaffolded ONCE and the brand owns every file in it afterwards — `src/main.js`, `gulpfile.js`, `hooks/build/pre.js` are yours by design — so there is nothing there for a brand file to shadow.
113
+
114
+ `omega customize` closes the loop from the other side: materializing a file writes the `omega:consumer-override:` marker into its own provenance header (`packages/web/src/overrides.js` `provenanceHeader()`), so the sanctioned way to take a copy produces a file the guard already accepts.
115
+
116
+ The monorepo itself is exempt — `packages/` is the framework's own source and `brands/` are the crew's fixtures — found by walking to the git root for a manifest named `omega` beside a `packages/` directory, which is what keeps a brand fixture from answering first. Everything else fails open: no `jq`, no brand root, no framework in the target's manifest, no install to read, and the write goes through. Covered by the guard cases in `scripts/agent-plugins.test.js`.
117
+
118
+ ## The quality hook
119
+
120
+ The four quality skills do not wait to be remembered. `hooks/quality/run.sh` serves two events from one script — so the surface table has one home — and fires them off the files a session actually edits:
121
+
122
+ | Surface written or edited | Skills asked for |
123
+ |---|---|
124
+ | a page (`*/pages/*.html`, `*/pages/*.md`), a layout, a `.liquid` template | `omega:seo`, `omega:accessibility` |
125
+ | the core head/foot chrome | `omega:seo`, `omega:accessibility` |
126
+ | an include, section, or component partial; page/core JS | `omega:accessibility` |
127
+ | `.scss` / `.css` | `omega:accessibility`, `omega:brandcheck` |
128
+ | `omega.json5`, section data JSON, a section schema | `omega:brandcheck` |
129
+ | a web flow page or auth module (`*/core/js/pages/*`, `*/core/js/libs/auth/*`) | `omega:analytics` (plus `omega:accessibility` from the core-JS row) |
130
+ | a backend payment route, payments-webhook or auth event | `omega:analytics` |
131
+ | the analytics package itself (`*/packages/analytics/*`) | `omega:analytics` |
132
+
133
+ On `PostToolUse` (Write|Edit) a match names its skills once per session per skill and records the file. On `Stop` the recorded list comes back as a block: the surfaces edited this session, the checklists they owe, and a refusal to sign off on an unreviewed pass. The block runs once per batch of edits (the list clears, so a later edit re-arms it) and never inside its own turn (`stop_hook_active`). Same scope guard as the shape hook, literally: both source `hooks/lib/omega-scope.sh`, which walks up from the edited file to the nearest `package.json` (stopping at the git root) and answers whether that project is or depends on `@omega.js/*`. The inject hook asks a different question — a project from a cwd, with its `functions/` manifest joined in — and keeps its own walk. Fail-open throughout. Covered by the quality cases in `scripts/agent-plugins.test.js`.
134
+
135
+ ## What is here, and what is not built yet
136
+
137
+ Thirteen skills — `main` (the hub: the package roster, the docs topology, the brand map, where project state lives), one router per package a session works in (`web`, `backend`, `desktop`, `extension`, `client`, `manager`), `browser` (driving the MCP router's Chrome upstreams), the four quality checklists (`seo`, `accessibility`, `brandcheck`, `analytics`) the quality hook fires on the surfaces they own, and `theme` (the cascade's own checklist), which the GATE fires on the theme surfaces in the table above rather than the quality hook. Each one names where the knowledge lives, in the monorepo and in a consumer project, and carries only the handful of rules a session needs before it knows which document to open. One thing is still open.
138
+
139
+ **The staleness mechanism.** This is the point of the move, not a bonus. Whatever ships needs something that fails when a skill names an export, a path, a config key, or a CLI command the code no longer has. A test in this repo is the strongest form; a generated section is next; a review trigger tied to a release is the floor. A plugin that goes stale quietly has only relocated the problem.
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env bash
2
+ # omega:gate mark — the ONE sanctioned way for an agent with NO Skill tool (the
3
+ # worker class writes its files through Bash) to record that it read the guide
4
+ # a skill routes to. It writes exactly the marker the hook's PostToolUse half
5
+ # writes, through the same lib, so the two lanes cannot drift.
6
+ # The main chat never needs this: invoking the skill records itself.
7
+ # Writing a marker by hand, or running this before reading the guide, is a
8
+ # process breach — the gate is a reading contract, not a lock to pick.
9
+ #
10
+ # Usage: mark.sh <skill> [--session <id>]
11
+ # The session id is --session when given (explicit beats ambient), else
12
+ # $CLAUDE_SESSION_ID, else $CLAUDE_CODE_SESSION_ID. The skill takes either
13
+ # spelling the Skill event takes (omega:web or bare web). Prints the marker
14
+ # path it wrote.
15
+
16
+ set -euo pipefail
17
+
18
+ usage() {
19
+ echo "usage: mark.sh <skill> [--session <id>] (e.g. mark.sh omega:web)" >&2
20
+ exit 1
21
+ }
22
+
23
+ skill=""
24
+ session="${CLAUDE_SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-}}"
25
+
26
+ while [ $# -gt 0 ]; do
27
+ case "$1" in
28
+ --session)
29
+ [ $# -ge 2 ] || usage
30
+ session="$2"
31
+ shift 2
32
+ ;;
33
+ -*) usage ;;
34
+ *)
35
+ [ -z "$skill" ] || usage
36
+ skill="$1"
37
+ shift
38
+ ;;
39
+ esac
40
+ done
41
+
42
+ [ -n "$skill" ] || usage
43
+ [ -n "$session" ] || usage
44
+
45
+ # The PostToolUse half records a bare name as its namespaced form; the same
46
+ # spelling has to unlock the same surface here.
47
+ case "$skill" in
48
+ omega:*) ;;
49
+ *) skill="omega:$skill" ;;
50
+ esac
51
+
52
+ # shellcheck source-path=SCRIPTDIR source=../lib/omega-gate.sh
53
+ . "$(dirname "${BASH_SOURCE[0]}")/../lib/omega-gate.sh"
54
+
55
+ marker=$(omega_gate_marker "$session" "$skill")
56
+ mkdir -p "$(omega_gate_state_dir)"
57
+ : > "$marker"
58
+ echo "$marker"
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bash
2
+ # omega:gate — PreToolUse (Write|Edit) + PostToolUse (Skill) hook
3
+ # The enforcement half of the inject hook: injecting a line only SUGGESTS the
4
+ # skill, and a session that skipped the line built a whole website target
5
+ # without ever reading the docs. So the surfaces a skill owns are refused until
6
+ # that skill was actually invoked — a target's tree, a brand's config/omega.json5,
7
+ # and a monorepo package that has a skill. Read-only tools are never in scope
8
+ # (the matcher is Write|Edit), and every other path stays free.
9
+ # One script for both events so the surface question has ONE answer; the event
10
+ # comes off hook_event_name. Fails open on anything unexpected.
11
+
12
+ set -euo pipefail
13
+
14
+ input=$(cat)
15
+
16
+ command -v jq >/dev/null 2>&1 || exit 0
17
+
18
+ event=$(jq -r '.hook_event_name // ""' <<<"$input" 2>/dev/null || true)
19
+ session_id=$(jq -r '.session_id // ""' <<<"$input" 2>/dev/null || true)
20
+
21
+ # The marker naming is shared with mark.sh, the sanctioned command for an agent
22
+ # with no Skill tool: one lib, so the two writers cannot drift apart.
23
+ gate_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-gate.sh"
24
+ [ -r "$gate_lib" ] || exit 0
25
+ # shellcheck source-path=SCRIPTDIR source=../lib/omega-gate.sh
26
+ . "$gate_lib"
27
+
28
+ state_dir=$(omega_gate_state_dir)
29
+
30
+ marker_for() {
31
+ omega_gate_marker "$session_id" "$1"
32
+ }
33
+
34
+ # --- PostToolUse (Skill): the record --------------------------------------
35
+ # The Skill tool's input names the skill it ran; the spelling is the tool's
36
+ # business, so both the namespaced form (omega:web) and the bare skill name
37
+ # (web, which the plugin namespaces) count as the same invocation.
38
+ if [ "$event" = "PostToolUse" ]; then
39
+ mkdir -p "$state_dir" 2>/dev/null || true
40
+ values=$(jq -r '[.tool_input // {} | .. | strings] | .[]' <<<"$input" 2>/dev/null || true)
41
+
42
+ # The brace group is what makes the failure silent: redirections apply left to
43
+ # right, so a bare `: > file 2>/dev/null` still prints its own failure.
44
+ while read -r skill; do
45
+ [ -n "$skill" ] || continue
46
+ { : > "$(marker_for "$skill")"; } 2>/dev/null || true
47
+ done < <(grep -oE 'omega:[a-z][a-z-]*' <<<"$values" 2>/dev/null || true)
48
+
49
+ while read -r name; do
50
+ [ -n "$name" ] || continue
51
+ { : > "$(marker_for "omega:$name")"; } 2>/dev/null || true
52
+ done < <(grep -xE '[a-z][a-z-]*' <<<"$values" 2>/dev/null || true)
53
+
54
+ exit 0
55
+ fi
56
+
57
+ # --- PreToolUse (Write|Edit): the refusal ---------------------------------
58
+ file_path=$(jq -r '.tool_input.file_path // ""' <<<"$input" 2>/dev/null || true)
59
+ [ -n "$file_path" ] || exit 0
60
+
61
+ skills_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-skills.sh"
62
+ [ -r "$skills_lib" ] || exit 0
63
+ # shellcheck source-path=SCRIPTDIR source=../lib/omega-skills.sh
64
+ . "$skills_lib"
65
+
66
+ # A surface can answer with MORE than one skill — a theme surface owns its
67
+ # framework's skill and omega:theme both — so the answer is read line by line
68
+ # and every skill has to have been invoked before the write goes through.
69
+ skills=$(omega_skill_for_file "$file_path")
70
+ [ -n "$skills" ] || exit 0
71
+
72
+ # No usable state dir means the record half could never have written a marker,
73
+ # so every write would refuse forever. Fail open instead of deadlocking.
74
+ mkdir -p "$state_dir" 2>/dev/null || true
75
+ { [ -d "$state_dir" ] && [ -w "$state_dir" ]; } || exit 0
76
+
77
+ missing=()
78
+ while read -r skill; do
79
+ [ -n "$skill" ] || continue
80
+ [ -f "$(marker_for "$skill")" ] && continue
81
+ missing+=("$skill")
82
+ done <<<"$skills"
83
+
84
+ [ "${#missing[@]}" -gt 0 ] || exit 0
85
+
86
+ skill=$(printf ', %s' "${missing[@]}")
87
+ skill="${skill:2}"
88
+
89
+ cat >&2 <<EOF
90
+ omega:gate — $skill has not been loaded, and owns this surface: $file_path
91
+ Invoke $skill via the Skill tool, read the framework map it routes to
92
+ (the brand's AGENTS.md import line, node_modules/@omega.js/AGENTS.md), and
93
+ then make this edit. The framework has conventions for this surface — pages,
94
+ sections, config keys, routes — and hand-rolling it is the failure this gate
95
+ exists to stop. Reading tools are free; this refusal only covers writes.
96
+ EOF
97
+ exit 2
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env bash
2
+ # omega:guard — PreToolUse (Write|Edit) hook
3
+ # The upstream-first boundary ([#452](https://github.com/Omega-JS-Stack/omega/issues/452)):
4
+ # inside a CONSUMER BRAND, an edit to a framework-owned file is refused, because
5
+ # a framework hole filled with a brand patch is a hole every later brand digs
6
+ # again. Two classes, treated differently:
7
+ # 1. generated or vendored (node_modules, dist, a generated header, the
8
+ # OMEGA-managed database.rules.json) — hard refusal, no escape hatch; the
9
+ # message names the real source to edit.
10
+ # 2. shadow copies — a brand file whose path mirrors a file the installed
11
+ # framework ships through its OVERRIDE LAYER, read from the live install.
12
+ # Refused with the upstream-first message and two exits: the in-file
13
+ # `omega:consumer-override:` marker, or OMEGA_CONSUMER_OVERRIDE=1.
14
+ # The monorepo itself is exempt — packages/ is the framework's source and
15
+ # brands/ are the crew's own fixtures. Fails open on anything unexpected.
16
+
17
+ set -euo pipefail
18
+
19
+ input=$(cat)
20
+
21
+ command -v jq >/dev/null 2>&1 || exit 0
22
+
23
+ file_path=$(jq -r '.tool_input.file_path // ""' <<<"$input" 2>/dev/null || true)
24
+ [ -n "$file_path" ] || exit 0
25
+ # Only a Write carries content — which is the only thing a brand-new shadow
26
+ # path can be judged on, since there is no file to read the marker out of yet.
27
+ content=$(jq -r '.tool_input.content // ""' <<<"$input" 2>/dev/null || true)
28
+
29
+ skills_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-skills.sh"
30
+ [ -r "$skills_lib" ] || exit 0
31
+ # shellcheck source-path=SCRIPTDIR source=../lib/omega-skills.sh
32
+ . "$skills_lib"
33
+
34
+ # --- scope: a consumer brand, and never this monorepo ----------------------
35
+ # The monorepo walk runs to the git root on its own, because a brand FIXTURE
36
+ # under brands/ answers the brand walk long before the monorepo root is reached.
37
+ in_monorepo() {
38
+ local dir="$1"
39
+ # `dirname` bottoms out at "." for a relative path and stays there forever,
40
+ # so an unanchored walk never terminates. Nothing to resolve, fail open.
41
+ case "$dir" in /*) ;; *) return 1 ;; esac
42
+ while [ -n "$dir" ] && [ "$dir" != "/" ]; do
43
+ if [ -f "$dir/package.json" ] && [ -d "$dir/packages" ] \
44
+ && [ "$(jq -r '.name // ""' "$dir/package.json" 2>/dev/null || true)" = "omega" ]; then
45
+ return 0
46
+ fi
47
+ [ -e "$dir/.git" ] && return 1
48
+ dir=$(dirname "$dir")
49
+ done
50
+ return 1
51
+ }
52
+
53
+ in_monorepo "$(dirname "$file_path")" && exit 0
54
+
55
+ brand=$(omega_brand_root "$(dirname "$file_path")")
56
+ [ -n "$brand" ] || exit 0
57
+ [ -f "$brand/package.json" ] || [ -f "$brand/config/omega.json5" ] || exit 0
58
+
59
+ rel="${file_path#"$brand"/}"
60
+
61
+ refuse() {
62
+ cat >&2
63
+ exit 2
64
+ }
65
+
66
+ # --- class 1: generated or vendored, no escape hatch -----------------------
67
+ case "$file_path" in
68
+ */node_modules/*)
69
+ refuse <<EOF
70
+ omega:guard — $rel is inside node_modules (an installed @omega.js package).
71
+ A dependency bug is fixed UPSTREAM: change it in the Omega monorepo and re-link
72
+ (\`omega i local\`), or file an issue on Omega-JS-Stack/omega. Patching an
73
+ install in place is erased by the next npm install and ships to nobody.
74
+ EOF
75
+ ;;
76
+ esac
77
+
78
+ case "$rel" in
79
+ dist/*|*/dist/*)
80
+ refuse <<EOF
81
+ omega:guard — $rel is build output (a dist/ tree).
82
+ Edit the SOURCE it is built from and re-run the target's build (\`npx omega build\`).
83
+ A hand edit to dist/ is gone the next time the verb runs.
84
+ EOF
85
+ ;;
86
+ esac
87
+
88
+ if [ "$(basename "$file_path")" = "database.rules.json" ]; then
89
+ refuse <<EOF
90
+ omega:guard — $rel carries the OMEGA-managed realtime-database rules block.
91
+ That block is generated: edit config/omega.json5 for what it reflects, and let
92
+ the target checks rewrite the file (\`npx omega test\` in the backend target).
93
+ The brand's OWN security rules source is firestore.rules, which is yours.
94
+ EOF
95
+ fi
96
+
97
+ # The header a framework writer stamps on a generated artifact. Read off the
98
+ # file on disk — the stamp is the artifact's own claim about itself.
99
+ if [ -f "$file_path" ]; then
100
+ header=$(head -n 20 "$file_path" 2>/dev/null || true)
101
+ if grep -q 'Generated by @omega\.js/' <<<"$header" \
102
+ || { grep -qi 'GENERATED FILE' <<<"$header" && grep -qi 'DO NOT EDIT' <<<"$header"; }; then
103
+ refuse <<EOF
104
+ omega:guard — $rel says in its own header that it is generated.
105
+ Edit the source it is rendered from — config/omega.json5, or the framework
106
+ template behind it — and re-run the verb that wrote it. Every edit here is
107
+ overwritten on the next build.
108
+ EOF
109
+ fi
110
+ fi
111
+
112
+ # --- class 2: shadow copies of the framework's override layer --------------
113
+ # The target the file belongs to, and the framework that owns that target. A
114
+ # brand with no targets/ directory (a single-target repo) is its own target.
115
+ target_root="$brand"
116
+ case "$file_path" in
117
+ "$brand"/targets/*/*)
118
+ rest="${file_path#"$brand"/targets/}"
119
+ target_root="$brand/targets/${rest%%/*}"
120
+ ;;
121
+ esac
122
+
123
+ framework=""
124
+ for manifest in "$target_root/package.json" "$target_root/functions/package.json"; do
125
+ [ -f "$manifest" ] || continue
126
+ while read -r dep; do
127
+ case "$dep" in
128
+ @omega.js/web|@omega.js/backend|@omega.js/desktop|@omega.js/extension)
129
+ framework="${dep#@omega.js/}"
130
+ break
131
+ ;;
132
+ esac
133
+ done < <(omega_manifest_deps "$manifest")
134
+ [ -n "$framework" ] && break
135
+ done
136
+ [ -n "$framework" ] || exit 0
137
+
138
+ # Read from the LIVE install, never a hardcoded list — the knowledge has to
139
+ # match the version this brand actually runs.
140
+ install=""
141
+ for candidate in "$target_root/node_modules/@omega.js/$framework" "$brand/node_modules/@omega.js/$framework"; do
142
+ if [ -d "$candidate" ]; then
143
+ install="$candidate"
144
+ break
145
+ fi
146
+ done
147
+ [ -n "$install" ] || exit 0
148
+
149
+ rel_target="${file_path#"$target_root"/}"
150
+
151
+ # THE lookup table: `<framework>|<consumer prefix, relative to the target
152
+ # root>|<framework root, glob allowed>`. A brand path under the prefix is
153
+ # stripped of it and looked up under the framework root; a hit means the brand
154
+ # file SHADOWS that framework file. ONE row per real override-layer root.
155
+ # web the MECHANISM lanes, mirroring src/overrides.js overrideLanes()
156
+ # (sections, includes, css) plus the engine's layered _layouts:
157
+ # first-layer-wins, consumer src/ → active theme → base → core.
158
+ # Sections live in the theme layers only (core ships none), and the
159
+ # css lane is the one sass resolves by layer.
160
+ # NOT here, on purpose: src/pages/ is CONTENT — the designed place
161
+ # for a brand's own copy, so a page is never guarded — and the js
162
+ # lane has no row at all, because page and layout modules are a
163
+ # UNION ([#624](https://github.com/Omega-JS-Stack/omega/issues/624),
164
+ # every layer's file runs) rather than a shadow.
165
+ # backend the two lanes that really replace a framework file BY NAME
166
+ # (src/manager/index.js: a consumer route or schema of the same name
167
+ # and method replaces the framework's), plus the framework half of
168
+ # the rules that ships in templates/.
169
+ # desktop and extension ship NO override layer: their src/defaults/ tree is
170
+ # scaffolded once and the brand owns every file in it afterwards, so there is
171
+ # nothing there to shadow.
172
+ SHADOW_ROOTS="
173
+ web|src/_layouts/|core/_layouts/
174
+ web|src/_layouts/|themes/*/_layouts/
175
+ web|src/_includes/|core/_includes/
176
+ web|src/_includes/|themes/*/_includes/
177
+ web|src/_sections/|themes/*/_sections/
178
+ web|src/_components/|themes/*/_components/
179
+ web|src/assets/css/|core/css/
180
+ web|src/assets/css/|themes/*/css/
181
+ backend|src/routes/|src/manager/routes/
182
+ backend|src/schemas/|src/manager/schemas/
183
+ backend||templates/
184
+ "
185
+
186
+ # The files the DOCS name as the consumer's own entry, and the seeds a brand
187
+ # owns once the target checks have written them. Exempt by name, never by guesswork:
188
+ # web main.scss is theming.md tier 1 and main.js/first-paint.js are the
189
+ # same REPLACE-with-extend lane in docs/web/index.md — a consumer
190
+ # file there reaches the framework's through `omega:main`, which is
191
+ # the documented way to own it.
192
+ # backend every seed in templates/ the target checks write once and never again
193
+ # (src/cli/commands/setup-tests/ in @omega.js/backend heals each).
194
+ case "$framework/$rel_target" in
195
+ web/src/assets/css/main.scss|web/src/assets/js/main.js|web/src/assets/js/first-paint.js)
196
+ exit 0
197
+ ;;
198
+ backend/firestore.rules|backend/storage.rules|backend/firebase.json|backend/firestore.indexes.json|backend/remoteconfig.template.json|backend/public/*|backend/config/*|backend/storage-lifecycle-*.json)
199
+ exit 0
200
+ ;;
201
+ esac
202
+
203
+ shadow=""
204
+ while IFS='|' read -r fw prefix root; do
205
+ [ -n "$fw" ] || continue
206
+ [ "$fw" = "$framework" ] || continue
207
+
208
+ sub="$rel_target"
209
+ if [ -n "$prefix" ]; then
210
+ case "$sub" in
211
+ "$prefix"*) sub="${sub#"$prefix"}" ;;
212
+ *) continue ;;
213
+ esac
214
+ fi
215
+ [ -n "$sub" ] || continue
216
+
217
+ # $root is deliberately unquoted so a themes/*/ row expands to every theme.
218
+ for candidate in "$install"/$root"$sub"; do
219
+ if [ -f "$candidate" ]; then
220
+ shadow="${candidate#"$install"/}"
221
+ break
222
+ fi
223
+ done
224
+ if [ -n "$shadow" ]; then break; fi
225
+ done <<EOF
226
+ $SHADOW_ROOTS
227
+ EOF
228
+
229
+ [ -n "$shadow" ] || exit 0
230
+
231
+ # The exits. The env flag covers a whole session; the marker covers one file
232
+ # forever, and lives in the first five lines in whatever comment syntax the
233
+ # file speaks (//, #, <!--, {#, /*).
234
+ [ "${OMEGA_CONSUMER_OVERRIDE:-}" = "1" ] && exit 0
235
+
236
+ if [ -f "$file_path" ] && head -n 5 "$file_path" 2>/dev/null | grep -qF 'omega:consumer-override:'; then
237
+ exit 0
238
+ fi
239
+ if [ -n "$content" ] && printf '%s\n' "$content" | head -n 5 | grep -qF 'omega:consumer-override:'; then
240
+ exit 0
241
+ fi
242
+
243
+ refuse <<EOF
244
+ omega:guard — $rel shadows @omega.js/$framework/$shadow (framework-owned).
245
+ If this is a framework gap, file an issue on Omega-JS-Stack/omega instead
246
+ (upstream-first). If this brand genuinely needs its own copy, add
247
+ \`// omega:consumer-override: <reason>\` to the top of the file and retry
248
+ (OMEGA_CONSUMER_OVERRIDE=1 skips this check for the session).
249
+ EOF
@@ -0,0 +1,63 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Write|Edit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/shape/run.sh"
10
+ },
11
+ {
12
+ "type": "command",
13
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/gate/run.sh"
14
+ },
15
+ {
16
+ "type": "command",
17
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/guard/run.sh"
18
+ }
19
+ ]
20
+ }
21
+ ],
22
+ "PostToolUse": [
23
+ {
24
+ "matcher": "Write|Edit",
25
+ "hooks": [
26
+ {
27
+ "type": "command",
28
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/quality/run.sh"
29
+ }
30
+ ]
31
+ },
32
+ {
33
+ "matcher": "Skill",
34
+ "hooks": [
35
+ {
36
+ "type": "command",
37
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/gate/run.sh"
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "Stop": [
43
+ {
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/quality/run.sh"
48
+ }
49
+ ]
50
+ }
51
+ ],
52
+ "UserPromptSubmit": [
53
+ {
54
+ "hooks": [
55
+ {
56
+ "type": "command",
57
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/inject/run.sh"
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+ }
63
+ }