@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.
- package/.claude-plugin/marketplace.json +14 -0
- package/LICENSE +98 -0
- package/README.md +165 -0
- package/bin/omega +2 -0
- package/bin/omg +2 -0
- package/claude-plugin/.claude-plugin/plugin.json +11 -0
- package/claude-plugin/.mcp.json +9 -0
- package/claude-plugin/README.md +139 -0
- package/claude-plugin/hooks/gate/mark.sh +58 -0
- package/claude-plugin/hooks/gate/run.sh +97 -0
- package/claude-plugin/hooks/guard/run.sh +249 -0
- package/claude-plugin/hooks/hooks.json +63 -0
- package/claude-plugin/hooks/inject/run.sh +127 -0
- package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
- package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
- package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
- package/claude-plugin/hooks/quality/run.sh +132 -0
- package/claude-plugin/hooks/shape/run.sh +45 -0
- package/claude-plugin/mcp-router-launch.js +29 -0
- package/claude-plugin/skills/README.md +48 -0
- package/claude-plugin/skills/accessibility/SKILL.md +31 -0
- package/claude-plugin/skills/analytics/SKILL.md +30 -0
- package/claude-plugin/skills/backend/SKILL.md +25 -0
- package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
- package/claude-plugin/skills/browser/SKILL.md +64 -0
- package/claude-plugin/skills/client/SKILL.md +24 -0
- package/claude-plugin/skills/desktop/SKILL.md +25 -0
- package/claude-plugin/skills/extension/SKILL.md +25 -0
- package/claude-plugin/skills/main/SKILL.md +54 -0
- package/claude-plugin/skills/manager/SKILL.md +25 -0
- package/claude-plugin/skills/seo/SKILL.md +36 -0
- package/claude-plugin/skills/theme/SKILL.md +33 -0
- package/claude-plugin/skills/web/SKILL.md +29 -0
- package/dist/cli-run.js +34 -0
- package/dist/cli.js +29 -0
- package/dist/commands/build.js +17 -0
- package/dist/commands/clean.js +16 -0
- package/dist/commands/company.js +46 -0
- package/dist/commands/deploy.js +143 -0
- package/dist/commands/dev.js +437 -0
- package/dist/commands/devlog.js +25 -0
- package/dist/commands/help.js +48 -0
- package/dist/commands/manage.js +53 -0
- package/dist/commands/migrate.js +76 -0
- package/dist/commands/onboard.js +31 -0
- package/dist/commands/pipeline.js +319 -0
- package/dist/commands/test.js +380 -0
- package/dist/commands/update.js +128 -0
- package/dist/commands/version.js +8 -0
- package/dist/company-init.js +167 -0
- package/dist/company.js +283 -0
- package/dist/config.js +1359 -0
- package/dist/devlog/index.js +226 -0
- package/dist/devlog/lib/collect-commits.js +136 -0
- package/dist/devlog/lib/generate-post.js +201 -0
- package/dist/devlog/lib/ghostii.js +122 -0
- package/dist/devlog/lib/project-map.js +98 -0
- package/dist/devlog/lib/publish-website.js +88 -0
- package/dist/index.js +45 -0
- package/dist/lib/agents-md.js +201 -0
- package/dist/lib/analytics-secret.js +22 -0
- package/dist/lib/argv.js +21 -0
- package/dist/lib/auth-admin.js +120 -0
- package/dist/lib/automation-client.js +210 -0
- package/dist/lib/backend-marketing.js +49 -0
- package/dist/lib/brand.js +240 -0
- package/dist/lib/bundle-id.js +53 -0
- package/dist/lib/claude-settings.js +125 -0
- package/dist/lib/company-scaffold.js +213 -0
- package/dist/lib/company.js +227 -0
- package/dist/lib/config-flow.js +350 -0
- package/dist/lib/config-write.js +41 -0
- package/dist/lib/custom-target.js +75 -0
- package/dist/lib/domain-utils.js +19 -0
- package/dist/lib/duration.js +39 -0
- package/dist/lib/env-order.js +236 -0
- package/dist/lib/env-secret.js +78 -0
- package/dist/lib/firestore-rest.js +326 -0
- package/dist/lib/framework-bin.js +156 -0
- package/dist/lib/gitignore.js +63 -0
- package/dist/lib/google-auth.js +495 -0
- package/dist/lib/google-token.js +66 -0
- package/dist/lib/jwt.js +31 -0
- package/dist/lib/legacy-oauth.js +59 -0
- package/dist/lib/node-version.js +127 -0
- package/dist/lib/owner-plan.js +78 -0
- package/dist/lib/package-scripts.js +152 -0
- package/dist/lib/preflight.js +470 -0
- package/dist/lib/product-create.js +144 -0
- package/dist/lib/run-command.js +74 -0
- package/dist/lib/run-gates.js +70 -0
- package/dist/lib/run-output.js +42 -0
- package/dist/lib/run-summary.js +384 -0
- package/dist/lib/scaffold.js +427 -0
- package/dist/lib/service-input.js +207 -0
- package/dist/lib/service-runner.js +466 -0
- package/dist/lib/stale.js +24 -0
- package/dist/lib/target-selection.js +155 -0
- package/dist/lib/verb-fanout.js +128 -0
- package/dist/lib/verify-live.js +188 -0
- package/dist/manage.js +311 -0
- package/dist/omega-bin.js +7 -0
- package/dist/onboard.js +532 -0
- package/dist/services/account/ensure/users.js +259 -0
- package/dist/services/account/index.js +97 -0
- package/dist/services/account/lib/backend-client.js +107 -0
- package/dist/services/account/lib/password.js +36 -0
- package/dist/services/account/lib/resolve-password.js +100 -0
- package/dist/services/advertising/ensure/sites.js +101 -0
- package/dist/services/advertising/index.js +101 -0
- package/dist/services/advertising/lib/adsense-api.js +41 -0
- package/dist/services/ai/ensure/keys.js +21 -0
- package/dist/services/ai/index.js +36 -0
- package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
- package/dist/services/analytics/ensure/google-streams.js +256 -0
- package/dist/services/analytics/ensure/meta-pixel.js +22 -0
- package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
- package/dist/services/analytics/index.js +134 -0
- package/dist/services/analytics/lib/analytics-api.js +156 -0
- package/dist/services/analytics/lib/meta-api.js +83 -0
- package/dist/services/analytics/lib/pixel-account.js +78 -0
- package/dist/services/analytics/lib/pixel-provision.js +152 -0
- package/dist/services/analytics/lib/pixel-specs.js +57 -0
- package/dist/services/analytics/lib/pixel-token.js +88 -0
- package/dist/services/analytics/lib/property-flow.js +77 -0
- package/dist/services/analytics/lib/tiktok-api.js +157 -0
- package/dist/services/analytics/lib/tiktok-auth.js +153 -0
- package/dist/services/assets/ensure/logo-gen.js +68 -0
- package/dist/services/assets/index.js +109 -0
- package/dist/services/assets/lib/assets-config.js +168 -0
- package/dist/services/assets/lib/brandmark-api.js +160 -0
- package/dist/services/assets/lib/derived.js +113 -0
- package/dist/services/assets/lib/font-loader.js +67 -0
- package/dist/services/assets/lib/reconcile.js +122 -0
- package/dist/services/assets/lib/reset.js +118 -0
- package/dist/services/assets/lib/svg-logo-generator.js +154 -0
- package/dist/services/assets/lib/svg-to-black.js +32 -0
- package/dist/services/assets/write/favicons.js +82 -0
- package/dist/services/assets/write/icons.js +64 -0
- package/dist/services/assets/write/process.js +96 -0
- package/dist/services/assets/write/reconcile.js +30 -0
- package/dist/services/assets/write/social-icons.js +108 -0
- package/dist/services/assets/write/templates.js +345 -0
- package/dist/services/bookmark/ensure/sync.js +255 -0
- package/dist/services/bookmark/index.js +17 -0
- package/dist/services/campaigns/ensure/contact-person.js +40 -0
- package/dist/services/campaigns/ensure/custom-fields.js +84 -0
- package/dist/services/campaigns/ensure/domain-auth.js +92 -0
- package/dist/services/campaigns/ensure/event-webhook.js +89 -0
- package/dist/services/campaigns/ensure/link-branding.js +187 -0
- package/dist/services/campaigns/ensure/list.js +50 -0
- package/dist/services/campaigns/ensure/segments.js +109 -0
- package/dist/services/campaigns/ensure/sender-identity.js +153 -0
- package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
- package/dist/services/campaigns/index.js +79 -0
- package/dist/services/campaigns/lib/dns-sync.js +81 -0
- package/dist/services/campaigns/lib/segment-query.js +138 -0
- package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
- package/dist/services/captcha/ensure/site-key.js +83 -0
- package/dist/services/captcha/index.js +78 -0
- package/dist/services/captcha/lib/console-url.js +45 -0
- package/dist/services/captcha/lib/recaptcha-api.js +36 -0
- package/dist/services/certificates/ensure/api-key.js +22 -0
- package/dist/services/certificates/ensure/bundle-ids.js +115 -0
- package/dist/services/certificates/ensure/certificates.js +187 -0
- package/dist/services/certificates/ensure/profiles.js +143 -0
- package/dist/services/certificates/index.js +225 -0
- package/dist/services/certificates/lib/apple-api.js +183 -0
- package/dist/services/certificates/lib/certificate-manager.js +252 -0
- package/dist/services/certificates/lib/identifier-manager.js +107 -0
- package/dist/services/certificates/lib/keychain.js +135 -0
- package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
- package/dist/services/certificates/lib/profile-manager.js +115 -0
- package/dist/services/chat/data/baseline-knowledge.md +96 -0
- package/dist/services/chat/ensure/chat.js +106 -0
- package/dist/services/chat/ensure/user.js +45 -0
- package/dist/services/chat/index.js +139 -0
- package/dist/services/chat/lib/baseline-knowledge.js +137 -0
- package/dist/services/cloud/ensure/authentication.js +267 -0
- package/dist/services/cloud/ensure/billing.js +120 -0
- package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
- package/dist/services/cloud/ensure/database.js +60 -0
- package/dist/services/cloud/ensure/firestore.js +79 -0
- package/dist/services/cloud/ensure/functions.js +49 -0
- package/dist/services/cloud/ensure/hosting.js +398 -0
- package/dist/services/cloud/ensure/oauth-consent.js +248 -0
- package/dist/services/cloud/ensure/project-settings.js +72 -0
- package/dist/services/cloud/ensure/sdk-config.js +95 -0
- package/dist/services/cloud/ensure/service-account.js +152 -0
- package/dist/services/cloud/ensure/services.js +103 -0
- package/dist/services/cloud/ensure/storage.js +47 -0
- package/dist/services/cloud/index.js +130 -0
- package/dist/services/cloud/lib/access-heal.js +130 -0
- package/dist/services/cloud/lib/firebase-api.js +662 -0
- package/dist/services/cloud/lib/project-flow.js +102 -0
- package/dist/services/directory/ensure/entry.js +48 -0
- package/dist/services/directory/index.js +64 -0
- package/dist/services/directory/lib/blocks.js +104 -0
- package/dist/services/disperse/index.js +45 -0
- package/dist/services/disperse/write/certs.js +117 -0
- package/dist/services/domain/ensure/nameservers.js +179 -0
- package/dist/services/domain/index.js +69 -0
- package/dist/services/domain/lib/namecheap-api.js +167 -0
- package/dist/services/domain/lib/registrars.js +46 -0
- package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
- package/dist/services/edge/ensure/cache-rules.js +105 -0
- package/dist/services/edge/ensure/dns-records.js +304 -0
- package/dist/services/edge/ensure/email-routing.js +292 -0
- package/dist/services/edge/ensure/rules-configuration.js +98 -0
- package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
- package/dist/services/edge/ensure/rules-redirect.js +107 -0
- package/dist/services/edge/ensure/rules-response-headers.js +90 -0
- package/dist/services/edge/ensure/rules-security.js +142 -0
- package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
- package/dist/services/edge/ensure/workers.js +219 -0
- package/dist/services/edge/ensure/zone-settings.js +108 -0
- package/dist/services/edge/ensure/zone.js +183 -0
- package/dist/services/edge/index.js +73 -0
- package/dist/services/edge/lib/cloudflare-api.js +84 -0
- package/dist/services/edge/lib/dns-records-helpers.js +518 -0
- package/dist/services/edge/lib/read-cache.js +16 -0
- package/dist/services/edge/lib/ruleset-helper.js +108 -0
- package/dist/services/edge/workers/omega-api-proxy.js +43 -0
- package/dist/services/email/data/baseline-filter.md +4 -0
- package/dist/services/email/data/baseline-knowledge.md +86 -0
- package/dist/services/email/ensure/agent.js +107 -0
- package/dist/services/email/ensure/user.js +45 -0
- package/dist/services/email/index.js +138 -0
- package/dist/services/email/lib/baseline.js +82 -0
- package/dist/services/email/lib/knowledge-file.js +53 -0
- package/dist/services/forms/ensure/form.js +46 -0
- package/dist/services/forms/ensure/user.js +45 -0
- package/dist/services/forms/index.js +138 -0
- package/dist/services/migrations/ensure/notifications.js +189 -0
- package/dist/services/migrations/ensure/orders.js +34 -0
- package/dist/services/migrations/ensure/payment-provider.js +132 -0
- package/dist/services/migrations/ensure/payments-intents.js +34 -0
- package/dist/services/migrations/ensure/state-retirement.js +266 -0
- package/dist/services/migrations/ensure/targets-rename.js +124 -0
- package/dist/services/migrations/ensure/users.js +1176 -0
- package/dist/services/migrations/index.js +101 -0
- package/dist/services/migrations/lib/attribution-touch.js +64 -0
- package/dist/services/migrations/lib/ensure-metadata.js +144 -0
- package/dist/services/migrations/lib/migration-runner.js +473 -0
- package/dist/services/migrations/lib/sanitize-strings.js +112 -0
- package/dist/services/migrations/lib/schema-validator.js +154 -0
- package/dist/services/monitoring/ensure/dsn.js +54 -0
- package/dist/services/monitoring/ensure/projects.js +135 -0
- package/dist/services/monitoring/index.js +54 -0
- package/dist/services/monitoring/lib/sentry-api.js +94 -0
- package/dist/services/newsletter/ensure/custom-fields.js +90 -0
- package/dist/services/newsletter/ensure/publication.js +94 -0
- package/dist/services/newsletter/ensure/segments.js +140 -0
- package/dist/services/newsletter/ensure/webhook.js +108 -0
- package/dist/services/newsletter/index.js +64 -0
- package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
- package/dist/services/newsletter/lib/segment-automation.js +577 -0
- package/dist/services/payment/ensure/chargebee-account.js +30 -0
- package/dist/services/payment/ensure/chargebee-products.js +359 -0
- package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
- package/dist/services/payment/ensure/paypal-account.js +36 -0
- package/dist/services/payment/ensure/paypal-products.js +374 -0
- package/dist/services/payment/ensure/paypal-webhook.js +128 -0
- package/dist/services/payment/ensure/stripe-account.js +93 -0
- package/dist/services/payment/ensure/stripe-disputes.js +56 -0
- package/dist/services/payment/ensure/stripe-products.js +245 -0
- package/dist/services/payment/ensure/stripe-radar.js +74 -0
- package/dist/services/payment/ensure/stripe-webhook.js +130 -0
- package/dist/services/payment/index.js +163 -0
- package/dist/services/payment/lib/chargebee-api.js +338 -0
- package/dist/services/payment/lib/payment-utils.js +116 -0
- package/dist/services/payment/lib/paypal-api.js +354 -0
- package/dist/services/payment/lib/provider-setup.js +134 -0
- package/dist/services/payment/lib/stripe-api.js +152 -0
- package/dist/services/repo/ensure/org.js +70 -0
- package/dist/services/repo/ensure/pages.js +72 -0
- package/dist/services/repo/ensure/repo.js +90 -0
- package/dist/services/repo/index.js +52 -0
- package/dist/services/repo/lib/github-api.js +196 -0
- package/dist/services/search/ensure/ga-link.js +57 -0
- package/dist/services/search/ensure/property.js +137 -0
- package/dist/services/search/ensure/sitemaps.js +70 -0
- package/dist/services/search/index.js +61 -0
- package/dist/services/search/lib/search-console-api.js +92 -0
- package/dist/services/seo/ensure/github-repos.js +271 -0
- package/dist/services/seo/index.js +55 -0
- package/dist/services/seo/lib/gh-api.js +161 -0
- package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
- package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
- package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
- package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
- package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
- package/dist/services/seo/templates/index.js +57 -0
- package/dist/services/server/ensure/brands.js +63 -0
- package/dist/services/server/index.js +42 -0
- package/dist/services/testing/ensure/target-checks.js +97 -0
- package/dist/services/testing/index.js +11 -0
- package/dist/services/testing/lib/checks.js +467 -0
- package/dist/services/update/index.js +20 -0
- package/dist/services/update/lib/cache.js +59 -0
- package/dist/services/update/lib/fingerprint.js +157 -0
- package/dist/services/update/write/targets.js +206 -0
- package/dist/services/workspace/ensure/agents.js +42 -0
- package/dist/services/workspace/ensure/claude-settings.js +34 -0
- package/dist/services/workspace/ensure/config.js +54 -0
- package/dist/services/workspace/ensure/defaults.js +60 -0
- package/dist/services/workspace/ensure/env-keys.js +55 -0
- package/dist/services/workspace/ensure/env-order.js +66 -0
- package/dist/services/workspace/ensure/env-rules.js +97 -0
- package/dist/services/workspace/ensure/gitignore.js +18 -0
- package/dist/services/workspace/ensure/scripts.js +126 -0
- package/dist/services/workspace/ensure/structure.js +97 -0
- package/dist/services/workspace/ensure/translation-sdk.js +148 -0
- package/dist/services/workspace/ensure/workflows.js +54 -0
- package/dist/services/workspace/index.js +8 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/certs.js +199 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/flows.js +317 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/prompt.js +187 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/translate/cache.js +84 -0
- package/dist/vendor/devkit/translate/engine.js +243 -0
- package/dist/vendor/devkit/translate/index.js +49 -0
- package/dist/vendor/devkit/translate/languages.js +134 -0
- package/dist/vendor/devkit/translate/providers.js +188 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/docs/AGENTS.md +200 -0
- package/docs/account.md +45 -0
- package/docs/advertising.md +46 -0
- package/docs/ai.md +34 -0
- package/docs/analytics.md +69 -0
- package/docs/assets.md +57 -0
- package/docs/bookmark.md +26 -0
- package/docs/brand.md +151 -0
- package/docs/campaigns.md +96 -0
- package/docs/captcha.md +46 -0
- package/docs/certificates.md +68 -0
- package/docs/chat.md +47 -0
- package/docs/cloud.md +110 -0
- package/docs/company.md +64 -0
- package/docs/directory.md +140 -0
- package/docs/disperse.md +46 -0
- package/docs/domain.md +56 -0
- package/docs/edge.md +234 -0
- package/docs/email.md +42 -0
- package/docs/forms.md +48 -0
- package/docs/index.md +109 -0
- package/docs/migration.md +203 -0
- package/docs/migrations.md +56 -0
- package/docs/monitoring.md +41 -0
- package/docs/newsletter.md +48 -0
- package/docs/payment.md +83 -0
- package/docs/repo.md +48 -0
- package/docs/search.md +44 -0
- package/docs/seo.md +34 -0
- package/docs/server.md +37 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/testing.md +34 -0
- package/docs/update.md +36 -0
- package/docs/workspace.md +64 -0
- package/package.json +88 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega:inject — UserPromptSubmit hook
|
|
3
|
+
# Reads the project's package.json and asks the session to invoke the matching
|
|
4
|
+
# framework skill. At a BRAND root the nearest manifest carries the manager
|
|
5
|
+
# alone, so the brand's targets are discovered too (config/omega.json5 and
|
|
6
|
+
# every targets/*/package.json) and the whole set is asked for at once, with
|
|
7
|
+
# the framework map named as required reading.
|
|
8
|
+
# Once per session per skill; fails open on anything unexpected.
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
input=$(cat)
|
|
13
|
+
|
|
14
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
15
|
+
|
|
16
|
+
session_id=$(jq -r '.session_id // ""' <<<"$input" 2>/dev/null || true)
|
|
17
|
+
cwd=$(jq -r '.cwd // ""' <<<"$input" 2>/dev/null || true)
|
|
18
|
+
[ -n "$cwd" ] && [ -d "$cwd" ] || exit 0
|
|
19
|
+
|
|
20
|
+
# The project's package.json: the cwd's own, else the nearest one above it —
|
|
21
|
+
# stopping at the git root, since past it is somebody else's project.
|
|
22
|
+
manifest=""
|
|
23
|
+
dir="$cwd"
|
|
24
|
+
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
25
|
+
if [ -f "$dir/package.json" ]; then
|
|
26
|
+
manifest="$dir/package.json"
|
|
27
|
+
break
|
|
28
|
+
fi
|
|
29
|
+
[ -e "$dir/.git" ] && break
|
|
30
|
+
dir=$(dirname "$dir")
|
|
31
|
+
done
|
|
32
|
+
[ -n "$manifest" ] || exit 0
|
|
33
|
+
|
|
34
|
+
# Backend apps keep @omega.js/backend in functions/package.json with a plain
|
|
35
|
+
# app manifest at the root, so the functions manifest joins the dep pool.
|
|
36
|
+
fn_manifest="$(dirname "$manifest")/functions/package.json"
|
|
37
|
+
|
|
38
|
+
own_name=$(jq -r '.name // empty' "$manifest" 2>/dev/null || true)
|
|
39
|
+
deps=$(jq -r '((.dependencies // {}) | keys) + ((.devDependencies // {}) | keys) | .[]' "$manifest" 2>/dev/null || true)
|
|
40
|
+
if [ -f "$fn_manifest" ]; then
|
|
41
|
+
fn_deps=$(jq -r '((.dependencies // {}) | keys) + ((.devDependencies // {}) | keys) | .[]' "$fn_manifest" 2>/dev/null || true)
|
|
42
|
+
deps=$(printf '%s\n%s' "$deps" "$fn_deps")
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# package → skill lives in the shared table (hooks/lib/omega-skills.sh), the one
|
|
46
|
+
# the gate hook reads too. These rows only say HOW a package matches: every row
|
|
47
|
+
# matches the manifest's OWN name, which is what covers working inside
|
|
48
|
+
# `packages/<pkg>` in the monorepo, and `name` rows match ONLY that way —
|
|
49
|
+
# web, desktop, and extension all depend on the client runtime, so a dependency
|
|
50
|
+
# on it says nothing about what the session works on.
|
|
51
|
+
skills_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-skills.sh"
|
|
52
|
+
[ -r "$skills_lib" ] || exit 0
|
|
53
|
+
# shellcheck source-path=SCRIPTDIR source=../lib/omega-skills.sh
|
|
54
|
+
. "$skills_lib"
|
|
55
|
+
|
|
56
|
+
matched=()
|
|
57
|
+
while read -r pkg signal; do
|
|
58
|
+
[ -n "$pkg" ] || continue
|
|
59
|
+
skill=$(omega_skill_for "$pkg")
|
|
60
|
+
[ -n "$skill" ] || continue
|
|
61
|
+
if [ "$own_name" = "$pkg" ]; then
|
|
62
|
+
matched+=("$skill")
|
|
63
|
+
elif [ "$signal" != "name" ] && grep -qxF "$pkg" <<<"$deps"; then
|
|
64
|
+
matched+=("$skill")
|
|
65
|
+
fi
|
|
66
|
+
done <<'MAP'
|
|
67
|
+
@omega.js/web any
|
|
68
|
+
@omega.js/backend any
|
|
69
|
+
@omega.js/desktop any
|
|
70
|
+
@omega.js/extension any
|
|
71
|
+
@omega.js/manager any
|
|
72
|
+
@omega.js/client name
|
|
73
|
+
omega name
|
|
74
|
+
MAP
|
|
75
|
+
|
|
76
|
+
# Brand-level discovery. A brand root's manifest carries @omega.js/manager and
|
|
77
|
+
# nothing else, so the frameworks a brand actually runs live one level down, in
|
|
78
|
+
# config/omega.json5 and each targets/*/package.json. Read them all: a session
|
|
79
|
+
# at a brand root has to know about every target before it edits one.
|
|
80
|
+
brand_root=$(omega_brand_root "$cwd")
|
|
81
|
+
if [ -n "$brand_root" ]; then
|
|
82
|
+
while read -r skill; do
|
|
83
|
+
[ -n "$skill" ] || continue
|
|
84
|
+
matched+=("$skill")
|
|
85
|
+
done < <(omega_brand_skills "$brand_root")
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
[ "${#matched[@]}" -gt 0 ] || exit 0
|
|
89
|
+
|
|
90
|
+
# One injection per session per skill.
|
|
91
|
+
marker_dir="${TMPDIR:-/tmp}/omega-inject"
|
|
92
|
+
mkdir -p "$marker_dir" 2>/dev/null || true
|
|
93
|
+
safe_session="${session_id//[^a-zA-Z0-9]/_}"
|
|
94
|
+
|
|
95
|
+
fresh=()
|
|
96
|
+
for skill in $(printf '%s\n' "${matched[@]}" | sort -u); do
|
|
97
|
+
marker="$marker_dir/${safe_session}__${skill//[:\/]/_}.loaded"
|
|
98
|
+
[ -f "$marker" ] && continue
|
|
99
|
+
: > "$marker" 2>/dev/null || true
|
|
100
|
+
fresh+=("$skill")
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
[ "${#fresh[@]}" -gt 0 ] || exit 0
|
|
104
|
+
|
|
105
|
+
if [ "${#fresh[@]}" -eq 1 ]; then
|
|
106
|
+
ctx="OMEGA project detected: invoke the ${fresh[0]} skill via the Skill tool before responding. Follow its rules and the framework docs it routes to for any work in this project. (Injected once per session; do not re-invoke on later prompts unless the work shifts.)"
|
|
107
|
+
else
|
|
108
|
+
skill_list=$(printf ', %s' "${fresh[@]}")
|
|
109
|
+
skill_list="${skill_list:2}"
|
|
110
|
+
ctx="OMEGA project detected: invoke these skills via the Skill tool before responding: ${skill_list}. Follow their rules and the framework docs they route to for any work in this project. (Injected once per session; do not re-invoke on later prompts unless the work shifts.)"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# In a brand, the skills and the framework map are REQUIRED reading before the
|
|
114
|
+
# first edit, not a suggestion — the gate hook refuses a target edit until the
|
|
115
|
+
# skill that owns it was invoked.
|
|
116
|
+
if [ -n "$brand_root" ]; then
|
|
117
|
+
ctx="$ctx
|
|
118
|
+
This is an OMEGA brand monorepo: every skill above, plus the framework map it points at (the brand AGENTS.md import line — node_modules/@omega.js/AGENTS.md), is required reading BEFORE the first edit. Writes under targets/ and to config/omega.json5 are refused until the skill owning that surface has been invoked."
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
jq -n --arg ctx "$ctx" '{
|
|
122
|
+
"hookSpecificOutput": {
|
|
123
|
+
"hookEventName": "UserPromptSubmit",
|
|
124
|
+
"additionalContext": $ctx
|
|
125
|
+
}
|
|
126
|
+
}'
|
|
127
|
+
exit 0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega gate markers — sourced by the two writers of a gate marker: the gate
|
|
3
|
+
# hook itself (PostToolUse Skill) and mark.sh (the one command an agent with no
|
|
4
|
+
# Skill tool runs after reading the guide). ONE home for where a marker lives
|
|
5
|
+
# and what it is called, so the two lanes can never disagree about the name.
|
|
6
|
+
|
|
7
|
+
# omega_gate_state_dir
|
|
8
|
+
# The marker directory. Under TMPDIR so it dies with the machine's temp state;
|
|
9
|
+
# never created here — each caller decides what an unusable directory means.
|
|
10
|
+
omega_gate_state_dir() {
|
|
11
|
+
printf '%s/omega-gate\n' "${TMPDIR:-/tmp}"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# omega_gate_marker <session_id> <skill>
|
|
15
|
+
# The marker path for one skill in one session. Both halves are flattened to
|
|
16
|
+
# safe filename characters, so a session id or a skill spelling can never walk
|
|
17
|
+
# out of the state directory.
|
|
18
|
+
omega_gate_marker() {
|
|
19
|
+
printf '%s/%s__%s.invoked\n' "$(omega_gate_state_dir)" "${1//[^a-zA-Z0-9]/_}" "${2//[:\/]/_}"
|
|
20
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega scope guard — sourced by the hooks that police a FILE path (shape,
|
|
3
|
+
# quality). One home for the question "is this file inside an omega project?",
|
|
4
|
+
# so the two guards can never disagree about what they police.
|
|
5
|
+
# The inject hook asks a different question (a project from a cwd, with its
|
|
6
|
+
# functions/ manifest joined in) and keeps its own walk.
|
|
7
|
+
|
|
8
|
+
# omega_scope <file_path>
|
|
9
|
+
# Walks up from the file to the nearest package.json, stopping at the git root
|
|
10
|
+
# (past it is somebody else's project), and succeeds only when that manifest IS
|
|
11
|
+
# or DEPENDS ON an @omega.js/* package. Returns 1 on no manifest, no jq, or
|
|
12
|
+
# unparseable JSON — the fail-open answer for a hook.
|
|
13
|
+
omega_scope() {
|
|
14
|
+
local file_path="$1"
|
|
15
|
+
[ -n "$file_path" ] || return 1
|
|
16
|
+
command -v jq >/dev/null 2>&1 || return 1
|
|
17
|
+
|
|
18
|
+
local dir manifest omega_linked
|
|
19
|
+
dir=$(dirname "$file_path")
|
|
20
|
+
manifest=""
|
|
21
|
+
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
22
|
+
if [ -f "$dir/package.json" ]; then
|
|
23
|
+
manifest="$dir/package.json"
|
|
24
|
+
break
|
|
25
|
+
fi
|
|
26
|
+
if [ -e "$dir/.git" ]; then
|
|
27
|
+
break
|
|
28
|
+
fi
|
|
29
|
+
dir=$(dirname "$dir")
|
|
30
|
+
done
|
|
31
|
+
[ -n "$manifest" ] || return 1
|
|
32
|
+
|
|
33
|
+
omega_linked=$(jq -r '
|
|
34
|
+
[.name // ""] + ((.dependencies // {}) | keys) + ((.devDependencies // {}) | keys)
|
|
35
|
+
| map(select(startswith("@omega.js/"))) | length
|
|
36
|
+
' "$manifest" 2>/dev/null || echo 0)
|
|
37
|
+
case "$omega_linked" in
|
|
38
|
+
''|*[!0-9]*) return 1 ;;
|
|
39
|
+
esac
|
|
40
|
+
[ "$omega_linked" -gt 0 ] || return 1
|
|
41
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega skill map — sourced by the hooks that answer "which skill owns this?"
|
|
3
|
+
# (inject, gate). ONE home for the framework → skill table and for the brand
|
|
4
|
+
# walk. The two hooks share the map but ask different questions of it: inject
|
|
5
|
+
# also reads config target keys, while the gate resolves a target from its
|
|
6
|
+
# manifest alone — a config-declared target with no manifest yet is asked for
|
|
7
|
+
# and not gated (fail-open by design).
|
|
8
|
+
# Every function fails open: unreadable files and unparseable JSON answer
|
|
9
|
+
# "nothing here", never an error.
|
|
10
|
+
|
|
11
|
+
# omega_skill_for <token>
|
|
12
|
+
# The one table — every hook that maps a thing to a skill reads THIS. Takes a
|
|
13
|
+
# package name (@omega.js/web), a config target key (web), or a monorepo
|
|
14
|
+
# package directory name (web): three spellings of the same fact. Prints the
|
|
15
|
+
# skill, or nothing when no skill owns the token:
|
|
16
|
+
# a custom target, `mobile` (parked), and the internal packages (devkit,
|
|
17
|
+
# config, account, analytics, monitoring, template-kit, mcp-router) all land
|
|
18
|
+
# here deliberately.
|
|
19
|
+
omega_skill_for() {
|
|
20
|
+
case "$1" in
|
|
21
|
+
@omega.js/web|web|website) echo 'omega:web' ;;
|
|
22
|
+
@omega.js/backend|backend) echo 'omega:backend' ;;
|
|
23
|
+
@omega.js/desktop|desktop) echo 'omega:desktop' ;;
|
|
24
|
+
@omega.js/extension|extension) echo 'omega:extension' ;;
|
|
25
|
+
@omega.js/manager|manager) echo 'omega:manager' ;;
|
|
26
|
+
@omega.js/client|client) echo 'omega:client' ;;
|
|
27
|
+
omega) echo 'omega:main' ;;
|
|
28
|
+
esac
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# omega_manifest_deps <manifest>
|
|
32
|
+
# Every dependency name in a package.json, both blocks, one per line.
|
|
33
|
+
omega_manifest_deps() {
|
|
34
|
+
[ -f "$1" ] || return 0
|
|
35
|
+
jq -r '((.dependencies // {}) | keys) + ((.devDependencies // {}) | keys) | .[]' "$1" 2>/dev/null || true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# omega_brand_root <dir>
|
|
39
|
+
# Walks up from a directory to the git root (inclusive) and prints the first
|
|
40
|
+
# BRAND root it finds: a directory carrying config/omega.json5, or one whose
|
|
41
|
+
# package.json depends on @omega.js/manager. Prints nothing when the walk
|
|
42
|
+
# leaves no brand behind — a framework package, a plain project, the monorepo
|
|
43
|
+
# root itself.
|
|
44
|
+
omega_brand_root() {
|
|
45
|
+
local dir="$1"
|
|
46
|
+
[ -n "$dir" ] || return 0
|
|
47
|
+
# `dirname` bottoms out at "." for a relative path and stays there forever,
|
|
48
|
+
# so the walk below would never terminate. Nothing to resolve, answer nothing.
|
|
49
|
+
case "$dir" in /*) ;; *) return 0 ;; esac
|
|
50
|
+
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
51
|
+
if [ -f "$dir/config/omega.json5" ]; then
|
|
52
|
+
printf '%s\n' "$dir"
|
|
53
|
+
return 0
|
|
54
|
+
fi
|
|
55
|
+
if [ -f "$dir/package.json" ] && omega_manifest_deps "$dir/package.json" | grep -qxF '@omega.js/manager'; then
|
|
56
|
+
printf '%s\n' "$dir"
|
|
57
|
+
return 0
|
|
58
|
+
fi
|
|
59
|
+
[ -e "$dir/.git" ] && return 0
|
|
60
|
+
dir=$(dirname "$dir")
|
|
61
|
+
done
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# omega_config_target_keys <config/omega.json5>
|
|
65
|
+
# The immediate child keys of the config's `targets` block, one per line. The
|
|
66
|
+
# config is JSON5 (comments, unquoted keys, trailing commas), so jq cannot read
|
|
67
|
+
# it and a key scan is the whole job: brace-depth tracking from the `targets:`
|
|
68
|
+
# line, printing keys at depth 1. Nothing here is load-bearing — a miss just
|
|
69
|
+
# means the key's skill has to come from the target's own manifest.
|
|
70
|
+
omega_config_target_keys() {
|
|
71
|
+
[ -r "$1" ] || return 0
|
|
72
|
+
awk '
|
|
73
|
+
BEGIN { started = 0; depth = 0 }
|
|
74
|
+
{
|
|
75
|
+
line = $0
|
|
76
|
+
# A comment starts at line start or after whitespace — never mid-token,
|
|
77
|
+
# which is what keeps a "https://…" value from eating its own braces.
|
|
78
|
+
sub(/^[[:space:]]*\/\/.*$/, "", line)
|
|
79
|
+
sub(/[[:space:]]\/\/.*$/, "", line)
|
|
80
|
+
}
|
|
81
|
+
!started {
|
|
82
|
+
if (line ~ /^[[:space:]]*"?targets"?[[:space:]]*:[[:space:]]*\{/) { started = 1; depth = 1 }
|
|
83
|
+
next
|
|
84
|
+
}
|
|
85
|
+
{
|
|
86
|
+
if (depth == 1 && line ~ /^[[:space:]]*["'"'"']?[A-Za-z_][A-Za-z0-9_-]*["'"'"']?[[:space:]]*:/) {
|
|
87
|
+
key = line
|
|
88
|
+
sub(/^[[:space:]]*/, "", key)
|
|
89
|
+
sub(/[[:space:]]*:.*$/, "", key)
|
|
90
|
+
gsub(/["'"'"']/, "", key)
|
|
91
|
+
print key
|
|
92
|
+
}
|
|
93
|
+
depth += gsub(/\{/, "{", line) - gsub(/\}/, "}", line)
|
|
94
|
+
if (depth <= 0) exit
|
|
95
|
+
}
|
|
96
|
+
' "$1" 2>/dev/null || true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# omega_brand_skills <brand_root>
|
|
100
|
+
# Every skill a brand session needs, one per line, unsorted and possibly
|
|
101
|
+
# repeated: omega:main and omega:manager (always, in a brand), plus one skill
|
|
102
|
+
# per target — read from every targets/*/package.json (and the functions/
|
|
103
|
+
# manifest a Firebase backend keeps its framework in) AND from the config's
|
|
104
|
+
# own target keys, so a target declared before its directory exists still
|
|
105
|
+
# counts. A target no framework owns contributes nothing.
|
|
106
|
+
omega_brand_skills() {
|
|
107
|
+
local root="$1" manifest dep key
|
|
108
|
+
echo 'omega:main'
|
|
109
|
+
echo 'omega:manager'
|
|
110
|
+
|
|
111
|
+
for manifest in "$root"/targets/*/package.json "$root"/targets/*/functions/package.json; do
|
|
112
|
+
[ -f "$manifest" ] || continue
|
|
113
|
+
while read -r dep; do
|
|
114
|
+
[ -n "$dep" ] || continue
|
|
115
|
+
omega_skill_for "$dep"
|
|
116
|
+
done < <(omega_manifest_deps "$manifest")
|
|
117
|
+
done
|
|
118
|
+
|
|
119
|
+
while read -r key; do
|
|
120
|
+
[ -n "$key" ] || continue
|
|
121
|
+
omega_skill_for "$key"
|
|
122
|
+
done < <(omega_config_target_keys "$root/config/omega.json5")
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# omega_theme_surface <path-relative-to-a-package-or-target-root>
|
|
126
|
+
# Whether a path is one of the theme cascade's OWN surfaces — the layers
|
|
127
|
+
# `resolveThemeLayers`/`overrideLanes` walk (packages/web's packaged themes, a
|
|
128
|
+
# consumer-local theme at src/themes/<id>, the section folders a consumer
|
|
129
|
+
# shadows — `_sections` AND `_components`, which overrideLanes resolves as one
|
|
130
|
+
# lane — and the tier-1 scss entry). One table serves the monorepo and a
|
|
131
|
+
# brand alike, since the caller passes the path relative to the package or
|
|
132
|
+
# target root.
|
|
133
|
+
omega_theme_surface() {
|
|
134
|
+
case "$1" in
|
|
135
|
+
themes/*|src/themes/*|src/_sections/*|src/_components/*|src/assets/css/main.scss) return 0 ;;
|
|
136
|
+
esac
|
|
137
|
+
return 1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# omega_skill_for_file <file_path>
|
|
141
|
+
# The skill(s) that OWN an editable surface, one per line, or nothing when no
|
|
142
|
+
# skill does. The surface's own skill comes first; omega:theme joins it on a
|
|
143
|
+
# theme surface (omega_theme_surface above), so a theme edit answers to both.
|
|
144
|
+
# Three surfaces gate, and only these three:
|
|
145
|
+
# <brand>/targets/<t>/** the target's own framework skill
|
|
146
|
+
# <brand>/config/omega.json5 omega:manager — the file the manage walk reconciles
|
|
147
|
+
# <monorepo>/packages/<pkg>/** that package's skill, where one exists
|
|
148
|
+
# Everything else — docs, scripts, the plugin's own files, a brand's root
|
|
149
|
+
# files, an internal package — answers nothing and stays free.
|
|
150
|
+
omega_skill_for_file() {
|
|
151
|
+
local file_path="$1"
|
|
152
|
+
[ -n "$file_path" ] || return 0
|
|
153
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
154
|
+
|
|
155
|
+
local brand rest target manifest skill
|
|
156
|
+
|
|
157
|
+
# The monorepo's own packages, ASKED FIRST: a package tree owns everything
|
|
158
|
+
# inside it, so a brand-shaped fixture living in one (devkit's test fixtures)
|
|
159
|
+
# is that package's business and never a brand of its own. The FIRST
|
|
160
|
+
# packages/ segment names the package — a nested packages/ inside a fixture
|
|
161
|
+
# cannot answer — and the manifest has to BE @omega.js/<pkg>; any other
|
|
162
|
+
# repo's packages/ directory falls through to the brand walk below.
|
|
163
|
+
case "$file_path" in
|
|
164
|
+
*/packages/*/*)
|
|
165
|
+
rest="${file_path#*/packages/}"
|
|
166
|
+
target="${rest%%/*}"
|
|
167
|
+
manifest="${file_path%/packages/"$rest"}/packages/$target/package.json"
|
|
168
|
+
if [ -f "$manifest" ] && [ "$(jq -r '.name // ""' "$manifest" 2>/dev/null || true)" = "@omega.js/$target" ]; then
|
|
169
|
+
skill=$(omega_skill_for "@omega.js/$target")
|
|
170
|
+
[ -n "$skill" ] && printf '%s\n' "$skill"
|
|
171
|
+
if [ "$skill" = 'omega:web' ] && omega_theme_surface "${rest#"$target"/}"; then
|
|
172
|
+
echo 'omega:theme'
|
|
173
|
+
fi
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
;;
|
|
177
|
+
esac
|
|
178
|
+
|
|
179
|
+
brand=$(omega_brand_root "$(dirname "$file_path")")
|
|
180
|
+
if [ -n "$brand" ]; then
|
|
181
|
+
case "$file_path" in
|
|
182
|
+
"$brand"/config/omega.json5)
|
|
183
|
+
echo 'omega:manager'
|
|
184
|
+
return 0
|
|
185
|
+
;;
|
|
186
|
+
"$brand"/targets/*/*)
|
|
187
|
+
rest="${file_path#"$brand"/targets/}"
|
|
188
|
+
target="${rest%%/*}"
|
|
189
|
+
for manifest in "$brand/targets/$target/package.json" "$brand/targets/$target/functions/package.json"; do
|
|
190
|
+
[ -f "$manifest" ] || continue
|
|
191
|
+
while read -r dep; do
|
|
192
|
+
[ -n "$dep" ] || continue
|
|
193
|
+
skill=$(omega_skill_for "$dep")
|
|
194
|
+
if [ -n "$skill" ]; then
|
|
195
|
+
printf '%s\n' "$skill"
|
|
196
|
+
# The cascade is a web mechanism, so only a website target's own
|
|
197
|
+
# theme surfaces add it — a themes/ dir in a backend is not one.
|
|
198
|
+
if [ "$skill" = 'omega:web' ] && omega_theme_surface "${rest#"$target"/}"; then
|
|
199
|
+
echo 'omega:theme'
|
|
200
|
+
fi
|
|
201
|
+
return 0
|
|
202
|
+
fi
|
|
203
|
+
done < <(omega_manifest_deps "$manifest")
|
|
204
|
+
done
|
|
205
|
+
return 0
|
|
206
|
+
;;
|
|
207
|
+
esac
|
|
208
|
+
fi
|
|
209
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega:quality — PostToolUse (Write|Edit) + Stop hook
|
|
3
|
+
# Fires the quality skills deterministically instead of by model judgment: a
|
|
4
|
+
# write to a web surface asks for the skills that own it (omega:seo,
|
|
5
|
+
# omega:accessibility, omega:brandcheck), a write to a flow or money surface
|
|
6
|
+
# asks for omega:analytics, and the Stop pass refuses a sign-off
|
|
7
|
+
# that never went through their checklists. One script for both events so the
|
|
8
|
+
# surface table has ONE home; the event comes off hook_event_name.
|
|
9
|
+
# Fails open on anything unexpected, and only polices projects that depend on
|
|
10
|
+
# (or are) @omega.js/*.
|
|
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
|
+
state_dir="${TMPDIR:-/tmp}/omega-quality"
|
|
22
|
+
safe_session="${session_id//[^a-zA-Z0-9]/_}"
|
|
23
|
+
pending="$state_dir/${safe_session}.pending"
|
|
24
|
+
|
|
25
|
+
# --- Stop: the re-check -------------------------------------------------------
|
|
26
|
+
# Blocks once on the web surfaces edited since the last block, then clears the
|
|
27
|
+
# list so a re-armed session needs a fresh edit. stop_hook_active means the
|
|
28
|
+
# block already ran on this turn.
|
|
29
|
+
if [ "$event" = "Stop" ]; then
|
|
30
|
+
stop_hook_active=$(jq -r '.stop_hook_active // false' <<<"$input" 2>/dev/null || true)
|
|
31
|
+
if [ "$stop_hook_active" = "true" ]; then
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
[ -s "$pending" ] || exit 0
|
|
35
|
+
|
|
36
|
+
# TAB-delimited on both sides: a path may contain spaces.
|
|
37
|
+
files=$(cut -d"$(printf '\t')" -f1 <"$pending" | sort -u)
|
|
38
|
+
skills=$(cut -d"$(printf '\t')" -f2 <"$pending" | tr ',' '\n' | sed '/^$/d' | sort -u | tr '\n' ',' | sed 's/,$//; s/,/, /g')
|
|
39
|
+
count=$(printf '%s\n' "$files" | grep -c . || true)
|
|
40
|
+
rm -f "$pending" 2>/dev/null || true
|
|
41
|
+
|
|
42
|
+
ctx="omega:quality — $count web surface(s) were edited this session:
|
|
43
|
+
$files
|
|
44
|
+
|
|
45
|
+
Before signing off, walk each edited surface against the checklists in: ${skills}. Invoke the skill via the Skill tool if it is not loaded, report what you checked, and fix what fails. If a checklist item does not apply to the change, say so — do not skip the pass silently."
|
|
46
|
+
|
|
47
|
+
jq -n --arg ctx "$ctx" '{
|
|
48
|
+
"decision": "block",
|
|
49
|
+
"reason": "omega:quality — edited web surfaces have not been reviewed against the quality checklists.",
|
|
50
|
+
"hookSpecificOutput": {
|
|
51
|
+
"hookEventName": "Stop",
|
|
52
|
+
"additionalContext": $ctx
|
|
53
|
+
}
|
|
54
|
+
}'
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# --- PostToolUse: the surface match ------------------------------------------
|
|
59
|
+
file_path=$(jq -r '.tool_input.file_path // ""' <<<"$input" 2>/dev/null || true)
|
|
60
|
+
[ -n "$file_path" ] || exit 0
|
|
61
|
+
|
|
62
|
+
# The surface table: a path pattern → the skills that own that surface. Rows
|
|
63
|
+
# accumulate, so head.html matches both its include row and its seo row.
|
|
64
|
+
matched=()
|
|
65
|
+
while read -r pattern skills; do
|
|
66
|
+
[ -n "$pattern" ] || continue
|
|
67
|
+
# The unquoted pattern is the point — case globs it.
|
|
68
|
+
# shellcheck disable=SC2254
|
|
69
|
+
case "$file_path" in
|
|
70
|
+
$pattern) matched+=("$skills") ;;
|
|
71
|
+
esac
|
|
72
|
+
done <<'MAP'
|
|
73
|
+
*/pages/*.html omega:seo,omega:accessibility
|
|
74
|
+
*/pages/*.md omega:seo,omega:accessibility
|
|
75
|
+
*/_layouts/* omega:seo,omega:accessibility
|
|
76
|
+
*.liquid omega:seo,omega:accessibility
|
|
77
|
+
*/_includes/core/head.html omega:seo
|
|
78
|
+
*/_includes/core/foot.html omega:seo
|
|
79
|
+
*/_includes/*.html omega:accessibility
|
|
80
|
+
*/sections/*.html omega:accessibility
|
|
81
|
+
*/components/*.html omega:accessibility
|
|
82
|
+
*/assets/js/*.js omega:accessibility
|
|
83
|
+
*/core/js/*.js omega:accessibility
|
|
84
|
+
*.scss omega:accessibility,omega:brandcheck
|
|
85
|
+
*.css omega:accessibility,omega:brandcheck
|
|
86
|
+
*/omega.json5 omega:brandcheck
|
|
87
|
+
*/_includes/*.json omega:brandcheck
|
|
88
|
+
*/sections/*.json5 omega:brandcheck
|
|
89
|
+
*/core/js/pages/* omega:analytics
|
|
90
|
+
*/core/js/libs/auth/* omega:analytics
|
|
91
|
+
*/routes/payments/* omega:analytics
|
|
92
|
+
*/events/firestore/payments-webhooks/* omega:analytics
|
|
93
|
+
*/events/auth/* omega:analytics
|
|
94
|
+
*/packages/analytics/* omega:analytics
|
|
95
|
+
MAP
|
|
96
|
+
|
|
97
|
+
[ "${#matched[@]}" -gt 0 ] || exit 0
|
|
98
|
+
|
|
99
|
+
# Scope guard: only police projects that depend on (or are) @omega.js/*.
|
|
100
|
+
scope_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-scope.sh"
|
|
101
|
+
[ -r "$scope_lib" ] || exit 0
|
|
102
|
+
# shellcheck source-path=SCRIPTDIR source=../lib/omega-scope.sh
|
|
103
|
+
. "$scope_lib"
|
|
104
|
+
omega_scope "$file_path" || exit 0
|
|
105
|
+
|
|
106
|
+
owners=$(printf '%s\n' "${matched[@]}" | tr ',' '\n' | sort -u | paste -sd, -)
|
|
107
|
+
|
|
108
|
+
# Arm the Stop re-check with this surface.
|
|
109
|
+
mkdir -p "$state_dir" 2>/dev/null || true
|
|
110
|
+
printf '%s\t%s\n' "$file_path" "$owners" >>"$pending" 2>/dev/null || true
|
|
111
|
+
|
|
112
|
+
# The reminder itself is once per session per skill — the same rule the inject
|
|
113
|
+
# hook follows. The Stop pass is what carries the per-file accounting.
|
|
114
|
+
fresh=()
|
|
115
|
+
for skill in $(printf '%s' "$owners" | tr ',' '\n'); do
|
|
116
|
+
marker="$state_dir/${safe_session}__${skill//[:\/]/_}.asked"
|
|
117
|
+
[ -f "$marker" ] && continue
|
|
118
|
+
: > "$marker" 2>/dev/null || true
|
|
119
|
+
fresh+=("$skill")
|
|
120
|
+
done
|
|
121
|
+
[ "${#fresh[@]}" -gt 0 ] || exit 0
|
|
122
|
+
|
|
123
|
+
skill_list=$(printf ', %s' "${fresh[@]}")
|
|
124
|
+
skill_list="${skill_list:2}"
|
|
125
|
+
|
|
126
|
+
jq -n --arg ctx "omega:quality — web surface edited ($file_path): invoke ${skill_list} via the Skill tool and hold this work to the checklists you find there. (Named once per session per skill; the Stop pass re-checks every edited surface before sign-off.)" '{
|
|
127
|
+
"hookSpecificOutput": {
|
|
128
|
+
"hookEventName": "PostToolUse",
|
|
129
|
+
"additionalContext": $ctx
|
|
130
|
+
}
|
|
131
|
+
}'
|
|
132
|
+
exit 0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# omega:shape — PreToolUse (Write|Edit) hook
|
|
3
|
+
# Bounces test files written in the three always-wrong shapes for this
|
|
4
|
+
# ecosystem: a __tests__/ path segment, a *.spec.js filename, and a
|
|
5
|
+
# test/tests/ nesting. The layer CHOICE stays judgment (docs/shared/testing.md
|
|
6
|
+
# owns the mantra); this guards only the mechanical suite shape. Fails open on
|
|
7
|
+
# anything unexpected, and only polices projects that depend on @omega.js/*.
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
input=$(cat)
|
|
12
|
+
|
|
13
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
14
|
+
|
|
15
|
+
file_path=$(jq -r '.tool_input.file_path // ""' <<<"$input" 2>/dev/null || true)
|
|
16
|
+
[ -n "$file_path" ] || exit 0
|
|
17
|
+
|
|
18
|
+
# Only test-shaped writes are in scope at all.
|
|
19
|
+
base=$(basename "$file_path")
|
|
20
|
+
case "$file_path" in
|
|
21
|
+
*__tests__/*|*/test/tests/*) ;;
|
|
22
|
+
*)
|
|
23
|
+
case "$base" in
|
|
24
|
+
*.spec.js|*.spec.ts|*.spec.mjs|*.spec.cjs) ;;
|
|
25
|
+
*) exit 0 ;;
|
|
26
|
+
esac
|
|
27
|
+
;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
# Scope guard: only police projects that depend on (or are) @omega.js/*.
|
|
31
|
+
scope_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/omega-scope.sh"
|
|
32
|
+
[ -r "$scope_lib" ] || exit 0
|
|
33
|
+
# shellcheck source-path=SCRIPTDIR source=../lib/omega-scope.sh
|
|
34
|
+
. "$scope_lib"
|
|
35
|
+
omega_scope "$file_path" || exit 0
|
|
36
|
+
|
|
37
|
+
cat >&2 <<EOF
|
|
38
|
+
omega:shape — test suite shape violation: $file_path
|
|
39
|
+
The omega ecosystem's mirrored suite shape (docs/shared/testing.md in the
|
|
40
|
+
Omega repo) has one home for tests: top-level test/ mirroring the source
|
|
41
|
+
tree, *.test.js filenames (desktop/extension FRAMEWORK suites live at
|
|
42
|
+
src/test/ — the recorded exception). Never __tests__/ directories, *.spec.*
|
|
43
|
+
names, or test/tests/ nesting. Write it as test/<mirror>/<name>.test.js.
|
|
44
|
+
EOF
|
|
45
|
+
exit 2
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The plugin's MCP entry — ONE launcher, correct in both eras
|
|
4
|
+
* ([#144](https://github.com/Omega-JS-Stack/omega/issues/144)).
|
|
5
|
+
*
|
|
6
|
+
* `.mcp.json` points at this file through `${CLAUDE_PLUGIN_ROOT}`, so the
|
|
7
|
+
* declaration never addresses a path outside the plugin. Node resolution from
|
|
8
|
+
* the plugin's OWN directory then finds the router wherever it lives: the
|
|
9
|
+
* workspace copy when the plugin is read live from this monorepo, and the
|
|
10
|
+
* installed `@omega.js/mcp-router` — wherever npm hoisted it — when the plugin
|
|
11
|
+
* is vendored into `@omega.js/manager` inside a consumer brand.
|
|
12
|
+
*
|
|
13
|
+
* The router package declares no `exports` map, so its bin is resolvable by
|
|
14
|
+
* subpath; requiring it starts the stdio server (which self-bootstraps its own
|
|
15
|
+
* dependencies on a bare checkout). Stdout is the MCP wire — the failure path
|
|
16
|
+
* speaks on stderr only, in the router's own voice.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const ROUTER_BIN = '@omega.js/mcp-router/bin/mcp-router.js';
|
|
20
|
+
|
|
21
|
+
let entry;
|
|
22
|
+
try {
|
|
23
|
+
entry = require.resolve(ROUTER_BIN, { paths: [__dirname] });
|
|
24
|
+
} catch {
|
|
25
|
+
process.stderr.write(`[mcp-router fatal] cannot resolve ${ROUTER_BIN} from ${__dirname} — install @omega.js/mcp-router beside the plugin\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
require(entry);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Skills — the authoring contract
|
|
2
|
+
|
|
3
|
+
One directory per skill, holding a `SKILL.md`. The directory name and the frontmatter `name` must match exactly, and both are BARE — no namespace. The plugin supplies the namespace, so `skills/web` surfaces in a session as `omega:web`.
|
|
4
|
+
|
|
5
|
+
The roster follows the packages a session works in: `main` (the hub) plus `web`, `backend`, `desktop`, `extension`, `client`, and `manager` — plus `browser`, which is not a package router but the usage pattern for the plugin's one MCP declaration, the `@omega.js/mcp-router` endpoint.
|
|
6
|
+
|
|
7
|
+
Four more are checklists rather than routers, and the quality hook fires them on the surfaces they own (the table is in the plugin README):
|
|
8
|
+
|
|
9
|
+
| Skill | The checklist |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `seo` | A page's search surface: meta title/description, canonical + social tags, structured data, one h1, sitemap/robots, link shape |
|
|
12
|
+
| `accessibility` | Front-end surfaces: landmarks and heading order, alt text, control names, color through the tokens, focus visibility, reduced motion |
|
|
13
|
+
| `brandcheck` | Config and copy consistency: brand facts read from omega.json5, one brand hex, the merge chain, no secrets in config |
|
|
14
|
+
| `analytics` | Event tracking: every flow fires through the catalog, a new event is a catalog entry first, the placement rule, consent and attribution carried not hand-rolled |
|
|
15
|
+
|
|
16
|
+
One more is a checklist the GATE fires, not the quality hook — the theme surfaces it owns are the same ones the gate refuses without it (the table is in the plugin README):
|
|
17
|
+
|
|
18
|
+
| Skill | The checklist |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `theme` | The theme cascade: which layer a change belongs to, base/skin/fork and the declared forks, the tokens, whole-folder overrides and `inherit`, the two consumer tiers |
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
skills/
|
|
24
|
+
└── <name>/
|
|
25
|
+
└── SKILL.md
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Frontmatter
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
---
|
|
32
|
+
name: <name>
|
|
33
|
+
description: <when to use it — one sentence, 300 characters or less>
|
|
34
|
+
user-invocable: true
|
|
35
|
+
---
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `description` is the whole loading decision — it is the only part Claude reads before choosing to load the skill — and every skill's sits in EVERY session, so it is a shared context budget. One tight sentence naming WHEN to invoke this skill: the package, the surfaces, the situations. Nothing about what the skill knows — the body and the docs carry that. `scripts/skill-descriptions.test.js` fails the structure lane on anything over 300 characters.
|
|
39
|
+
|
|
40
|
+
## The body points; the repo docs are the source
|
|
41
|
+
|
|
42
|
+
A skill is a router. It names where the truth lives for BOTH worlds — `docs/<framework>/index.md` plus `docs/shared/` when the session is in this monorepo, the top-level map through `node_modules/@omega.js/AGENTS.md` (the scope symlink the workspace service maintains) plus `docs/manager/brand.md` when the session is in a consumer project — and carries only what a session needs before it knows which document to open: the hard rules, the shape of the thing, and the paths.
|
|
43
|
+
|
|
44
|
+
Content copied out of the docs into a skill is a second home for the same fact, and the copy is what goes stale. Point instead.
|
|
45
|
+
|
|
46
|
+
## Keeping it honest
|
|
47
|
+
|
|
48
|
+
Every skill has to be checkable against the code it describes. Prefer claims a test can verify — an exported name, a config key, a CLI command, a file path — over prose that can drift without any signal. See the "staleness mechanism" section in the plugin README.
|