From 286401e1df80ab4c5976d5a3fc6e7b8731075d93 Mon Sep 17 00:00:00 2001 From: sherwinski Date: Fri, 9 Oct 2026 12:21:32 -0700 Subject: [PATCH 1/5] feat: [SDK-5456] add starter prompts, dark-theme brand assets, and a fuller listing description The ChatGPT / Codex directory builds the starter-prompt banner from `interface.defaultPrompt`, and each chip shows `composerIcon` in `brandColor`. On the dark theme the navy logomark and `#051B2C` label are not readable, so this change adds the official white logomark from the OneSignal media kit as `logoDark` and `composerIconDark`, and the brand purple `#4E50D1` as `brandColorDark` (2.6:1 against `#212121`). `interface.longDescription` now follows the structure of the Canva listing: what OneSignal is, what the plugin can do, how to invoke it, example prompts, requirements, and the safety rules. The bundle gate now checks every asset field the manifest sets and rejects `interface.screenshots`, which a Skills-only upload refuses. No version bump: main is already at 1.1.1 ahead of the 1.1.0 tag. --- .codex-plugin/plugin.json | 10 +++++--- AGENT.md | 4 +++- assets/logomark-white.svg | 3 +++ scripts/package_directory_bundle.py | 37 +++++++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 assets/logomark-white.svg diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 40a15dd..9fd9fed 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -21,7 +21,7 @@ "interface": { "displayName": "OneSignal", "shortDescription": "Set up and verify OneSignal", - "longDescription": "Install and initialize the OneSignal SDK, configure push credentials, and verify delivery. The bundled helper scripts need Python 3.7 or newer on PATH; the setup skill checks for it first and offers by-hand fallbacks when it is missing.", + "longDescription": "OneSignal is the customer messaging platform for push notifications, in-app messages, email, and SMS. This plugin brings OneSignal onboarding into Codex: point it at your codebase and it installs the SDK, sets up your push credentials, and proves that a real notification reaches a real device.\n\nWhat the OneSignal plugin can do:\nDetect your platform: Reads your project manifests to identify web (including Next.js, React, Vue, Angular, and Vite), iOS, Android, React Native, Expo, Flutter, Cordova, Capacitor, or Unity.\nInstall the SDK: Adds the OneSignal SDK with an exact, current version pin and the initialization code for your framework, in your existing code style and package manager.\nConfigure push credentials: Walks you through the Apple Developer and Firebase console steps, then uploads your APNs .p8 key and FCM service-account JSON to OneSignal for you. Guides email domain (SPF, DKIM, DMARC) and SMS sender setup.\nVerify real delivery: Builds and runs your app, waits for the first device subscription to register, sends a test push, and confirms on the server that it was delivered.\nDiagnose failures: Finds out why a notification does not arrive, such as missing credentials, a Site URL that does not match your origin, a service worker on the wrong origin, or a device that never subscribed.\nKeep secrets out of your code: Reads API keys from environment variables, writes a gitignored .env, and scans its own changes for secrets before it finishes.\nShow every change first: Declares the file list up front and shows the full diff for one approval before it writes.\n\nOnce installed, describe what you want in plain language or invoke the plugin directly with @OneSignal.\n\nTry prompts like:\n@OneSignal, set up push notifications in this Next.js app.\n@OneSignal, add the OneSignal SDK to my Expo project.\n@OneSignal, upload my APNs .p8 key and Firebase service account.\n@OneSignal, why isn't my push notification arriving on Android?\n@OneSignal, send a test push to my device and confirm delivery.\n@OneSignal, check that my service worker is served from the right origin.\n\nRequirements: A free OneSignal account and your App ID. A REST API key exported as ONESIGNAL_REST_API_KEY; the plugin never asks you to paste it into chat. Python 3.7 or newer on PATH for the helper scripts; if it is missing, the setup skill offers by-hand steps instead. A device, simulator, or browser that can receive the test push. Optional: sign in to the OneSignal MCP server so the plugin can look up users, check delivery, and send test messages as first-class tools.\n\nEvery edit happens on your machine through your local agent, with your approval. The plugin sends no source code, file paths, or credentials to OneSignal.", "developerName": "OneSignal", "category": "Developer Tools", "capabilities": [ @@ -33,10 +33,14 @@ "termsOfServiceURL": "https://onesignal.com/tos", "defaultPrompt": [ "Set up OneSignal in this app.", - "Verify that OneSignal push delivery works." + "Upload my APNs and FCM credentials to OneSignal.", + "Send a test push to my device and confirm delivery." ], "brandColor": "#051B2C", + "brandColorDark": "#4E50D1", "composerIcon": "./assets/logomark.png", - "logo": "./assets/logomark.png" + "composerIconDark": "./assets/logomark-white.svg", + "logo": "./assets/logomark.png", + "logoDark": "./assets/logomark-white.svg" } } diff --git a/AGENT.md b/AGENT.md index 95b9808..469ea2d 100644 --- a/AGENT.md +++ b/AGENT.md @@ -136,7 +136,9 @@ builds that artifact from this tree at release time: - It writes `.codex-plugin/plugin.json` from the repository manifest without `mcpServers`, because a Skills-only upload rejects MCP configuration (the listing's MCP server is attached - in the portal). It copies `assets/` so `interface.logo` and `interface.composerIcon` resolve. + in the portal). It copies `assets/` so `interface.logo`, `interface.composerIcon`, and + their `Dark` variants resolve. The gate rejects `interface.screenshots`, which a + Skills-only upload refuses. - It copies each skill folder under `skills/` (`skills/setup/`, `skills/credentials/`, `skills/verify/`), and gives each one its own `references/`, `endpoint.conf`, and the runtime scripts that skill calls (a table in the script names them). diff --git a/assets/logomark-white.svg b/assets/logomark-white.svg new file mode 100644 index 0000000..e9c6b6b --- /dev/null +++ b/assets/logomark-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/scripts/package_directory_bundle.py b/scripts/package_directory_bundle.py index 14d4db8..792ca77 100755 --- a/scripts/package_directory_bundle.py +++ b/scripts/package_directory_bundle.py @@ -80,6 +80,10 @@ # single hyphens are what the submission rules accept. PLUGIN_NAME_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$") BRAND_ASSET_FIELDS = ("logo", "composerIcon") +# Dark-theme variants. The directory falls back to the light file when one is absent. +OPTIONAL_BRAND_ASSET_FIELDS = ("logoDark", "composerIconDark") +# A Skills-only upload rejects this field (`screenshot_configuration_excluded`). +EXCLUDED_INTERFACE_FIELDS = ("screenshots",) VERSION_FILES = { "claude": ".claude-plugin/plugin.json", @@ -218,6 +222,11 @@ def bundle_manifest(manifest): return bundled +def brand_asset_fields(interface): + """The required asset fields, plus every optional one the manifest sets.""" + return BRAND_ASSET_FIELDS + tuple(f for f in OPTIONAL_BRAND_ASSET_FIELDS if f in interface) + + def check_manifest(source, findings): """Check the fields the directory reads from the manifest and the files they point to.""" manifest = read_manifest(source) @@ -237,12 +246,15 @@ def check_manifest(source, findings): if not isinstance(interface, dict): findings.append("%s: interface is missing" % CODEX_MANIFEST) return - for field in BRAND_ASSET_FIELDS: + for field in brand_asset_fields(interface): path = interface.get(field) if not isinstance(path, str) or not path.startswith("./%s/" % ASSETS_DIR): findings.append("%s: interface.%s must point into ./%s/ (got %r)" % (CODEX_MANIFEST, field, ASSETS_DIR, path)) elif not os.path.isfile(os.path.join(source, path[2:])): findings.append("%s: interface.%s points to %s, which does not exist" % (CODEX_MANIFEST, field, path)) + for field in EXCLUDED_INTERFACE_FIELDS: + if field in interface: + findings.append("%s: interface.%s is rejected by a Skills-only upload; remove it" % (CODEX_MANIFEST, field)) # --------------------------------------------------------------------------- @@ -377,10 +389,13 @@ def check_bundle_manifest(bundle_dir, findings): if os.path.exists(os.path.join(bundle_dir, ".mcp.json")): findings.append(".mcp.json must not ship in a Skills-only bundle") interface = manifest.get("interface") or {} - for field in BRAND_ASSET_FIELDS: + for field in brand_asset_fields(interface): path = interface.get(field) if not isinstance(path, str) or not os.path.isfile(os.path.join(bundle_dir, path)): findings.append("%s: interface.%s (%r) does not resolve inside the bundle" % (CODEX_MANIFEST, field, path)) + for field in EXCLUDED_INTERFACE_FIELDS: + if field in interface: + findings.append("%s: interface.%s must not ship in a Skills-only bundle" % (CODEX_MANIFEST, field)) def check_bundle(bundle_dir): @@ -613,6 +628,24 @@ def self_test(source): os.remove(os.path.join(bad, ASSETS_DIR, "logomark.png")) ok = expect_failure("manifest logo that points to a missing file", bad, os.path.join(tmp, "bad-brand-asset-work"), "interface.logo points to ./assets/logomark.png, which does not exist") and ok + + bad = os.path.join(tmp, "bad-dark-brand-asset") + copy_source_subset(source, bad) + path = os.path.join(bad, CODEX_MANIFEST) + manifest = json.loads(read_text(path)) + manifest["interface"]["logoDark"] = "./assets/does-not-exist.svg" + write_text(path, json.dumps(manifest, indent=2) + "\n") + ok = expect_failure("manifest logoDark that points to a missing file", bad, os.path.join(tmp, "bad-dark-brand-asset-work"), + "interface.logoDark points to ./assets/does-not-exist.svg, which does not exist") and ok + + bad = os.path.join(tmp, "bad-screenshots") + copy_source_subset(source, bad) + path = os.path.join(bad, CODEX_MANIFEST) + manifest = json.loads(read_text(path)) + manifest["interface"]["screenshots"] = ["./assets/logomark.png"] + write_text(path, json.dumps(manifest, indent=2) + "\n") + ok = expect_failure("interface.screenshots in the manifest", bad, os.path.join(tmp, "bad-screenshots-work"), + "interface.screenshots is rejected by a Skills-only upload") and ok return ok From 9580b99b634b1207efadd163af0cdd73d6ccd8f6 Mon Sep 17 00:00:00 2001 From: sherwinski Date: Fri, 9 Oct 2026 14:39:21 -0700 Subject: [PATCH 2/5] docs: update project description --- .codex-plugin/plugin.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 9fd9fed..3f0606d 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -20,8 +20,8 @@ "mcpServers": "./.mcp.json", "interface": { "displayName": "OneSignal", - "shortDescription": "Set up and verify OneSignal", - "longDescription": "OneSignal is the customer messaging platform for push notifications, in-app messages, email, and SMS. This plugin brings OneSignal onboarding into Codex: point it at your codebase and it installs the SDK, sets up your push credentials, and proves that a real notification reaches a real device.\n\nWhat the OneSignal plugin can do:\nDetect your platform: Reads your project manifests to identify web (including Next.js, React, Vue, Angular, and Vite), iOS, Android, React Native, Expo, Flutter, Cordova, Capacitor, or Unity.\nInstall the SDK: Adds the OneSignal SDK with an exact, current version pin and the initialization code for your framework, in your existing code style and package manager.\nConfigure push credentials: Walks you through the Apple Developer and Firebase console steps, then uploads your APNs .p8 key and FCM service-account JSON to OneSignal for you. Guides email domain (SPF, DKIM, DMARC) and SMS sender setup.\nVerify real delivery: Builds and runs your app, waits for the first device subscription to register, sends a test push, and confirms on the server that it was delivered.\nDiagnose failures: Finds out why a notification does not arrive, such as missing credentials, a Site URL that does not match your origin, a service worker on the wrong origin, or a device that never subscribed.\nKeep secrets out of your code: Reads API keys from environment variables, writes a gitignored .env, and scans its own changes for secrets before it finishes.\nShow every change first: Declares the file list up front and shows the full diff for one approval before it writes.\n\nOnce installed, describe what you want in plain language or invoke the plugin directly with @OneSignal.\n\nTry prompts like:\n@OneSignal, set up push notifications in this Next.js app.\n@OneSignal, add the OneSignal SDK to my Expo project.\n@OneSignal, upload my APNs .p8 key and Firebase service account.\n@OneSignal, why isn't my push notification arriving on Android?\n@OneSignal, send a test push to my device and confirm delivery.\n@OneSignal, check that my service worker is served from the right origin.\n\nRequirements: A free OneSignal account and your App ID. A REST API key exported as ONESIGNAL_REST_API_KEY; the plugin never asks you to paste it into chat. Python 3.7 or newer on PATH for the helper scripts; if it is missing, the setup skill offers by-hand steps instead. A device, simulator, or browser that can receive the test push. Optional: sign in to the OneSignal MCP server so the plugin can look up users, check delivery, and send test messages as first-class tools.\n\nEvery edit happens on your machine through your local agent, with your approval. The plugin sends no source code, file paths, or credentials to OneSignal.", + "shortDescription": "Set up and send push notifications", + "longDescription": "OneSignal is the market leading customer engagement solution for push notifications, email, SMS, in-app messaging, and Live Activities. This plugin brings OneSignal onboarding into Codex: point it at your codebase and it installs the SDK, sets up your push credentials, and verifies that a real notification reaches your device.\n\nOnce installed, describe what you want in plain language or invoke the plugin directly with @OneSignal.\n\nTry prompts like:\n@OneSignal set up push notifications in this app.\n@OneSignal upload my APNs .p8 key and Firebase service account to OneSignal.\n@OneSignal why isn't my push notification arriving on Android?\n@OneSignal send a test push to my device and confirm delivery.\n\nRequirements: A free OneSignal account. A device, simulator, or browser that can receive push notifications.", "developerName": "OneSignal", "category": "Developer Tools", "capabilities": [ From e727df0d8fa4f5b55a041b6674afeb8312c07d19 Mon Sep 17 00:00:00 2001 From: sherwinski Date: Fri, 9 Oct 2026 17:26:09 -0700 Subject: [PATCH 3/5] docs: update each SKILL's description to be more succinct Each description renders as a single line in the plugin listing. Long descriptions get truncated, where a user can then view them by clicking on the skill card itself. Therefore, the truncated description should still offer enough detail to give a users a sense of what they are used for. --- skills/credentials/SKILL.md | 2 +- skills/setup/SKILL.md | 2 +- skills/verify/SKILL.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/credentials/SKILL.md b/skills/credentials/SKILL.md index ad5b9ec..46f0b10 100644 --- a/skills/credentials/SKILL.md +++ b/skills/credentials/SKILL.md @@ -1,6 +1,6 @@ --- name: credentials -description: Guides a OneSignal customer through procuring and configuring the platform push/messaging credentials that only a human can start in an external console — Apple APNs .p8 keys, Firebase FCM v1 service-account JSON, web Site URL / Safari certs, email SPF/DKIM/DMARC DNS records, and SMS sender registration. Use when the user says push isn't delivering after SDK install, asks to "set up APNs", "add my .p8", "connect Firebase / FCM", "upload push credentials", "why is Android/iOS push failing", "configure email domain / DNS", "set up SMS/texting", or when another OneSignal skill reports a platform is missing credentials. The agent walks the human through the portal steps, then finishes the API-uploadable ones (Apple .p8, Firebase JSON) itself via the OneSignal apps API, validating the response and keeping every secret file out of the repo. +description: Upload your APNs .p8 key, Firebase FCM service-account JSON, or web Site URL to OneSignal, and get guided setup for Safari certs, email SPF/DKIM/DMARC DNS records, and SMS sender registration. argument-hint: "[platform=ios|android|web|email|sms] [app=]" --- diff --git a/skills/setup/SKILL.md b/skills/setup/SKILL.md index 63e298b..ef960ea 100644 --- a/skills/setup/SKILL.md +++ b/skills/setup/SKILL.md @@ -1,6 +1,6 @@ --- name: setup -description: Entry-point OneSignal onboarding skill. Use when a developer wants to add, install, integrate, initialize, or "set up" the OneSignal SDK in their own codebase (web, iOS, Android, React Native, Expo, Flutter, Cordova/Ionic/Capacitor, Unity) — triggers on "set up OneSignal", "add push notifications", "install the OneSignal SDK", "integrate OneSignal", "onboard onto OneSignal", or a fresh project with no OneSignal present. Supports one-command invocation with arguments, e.g. "/onesignal:setup app=". Detects the platform/framework from project manifests, gates on push credentials FIRST (uploading them via the provisioning endpoint before any SDK code is written), installs and initializes the SDK, adds a debug-only verification helper, and hands off to the verify skill. +description: Set up OneSignal in your codebase by asking "set up OneSignal". Detects the platform/framework from your project, guides you through uploading push credentials, installs and sets up the SDK, then hands off to the verify skill. argument-hint: app= --- diff --git a/skills/verify/SKILL.md b/skills/verify/SKILL.md index bc3b861..506f79a 100644 --- a/skills/verify/SKILL.md +++ b/skills/verify/SKILL.md @@ -1,6 +1,6 @@ --- name: verify -description: Closed-loop verification that a OneSignal integration actually works end to end — builds/runs the app, waits for the first real device subscription to register, checks identity, sends a real test push, and confirms server-side delivery. Use after the SDK-install or credentials skills have run, or whenever the user asks to "verify OneSignal works", "test push delivery", "prove the integration works", "why isn't my notification arriving", "confirm the device registered", "send myself a test notification", or is debugging an install that appears complete but delivers nothing. This is the "prove it works" step — it does NOT install the SDK or upload credentials; if those are missing it routes to the appropriate skill. +description: Verify that your OneSignal integration works end to end: builds/runs your app, waits for the first real device subscription to register, sends a real test push, and confirms server-side delivery. argument-hint: "[app=]" --- From d86f25f46936923cddd959ec163a8def6124bdd0 Mon Sep 17 00:00:00 2001 From: sherwinski Date: Fri, 9 Oct 2026 17:42:08 -0700 Subject: [PATCH 4/5] docs: [SDK-5456] use one plugin description across both manifests and the README The Claude manifest, the marketplace manifest, the Codex root `description`, and the README snippet each described the plugin in different words. They now share one sentence that matches the voice of the Codex `longDescription`. --- .claude-plugin/marketplace.json | 4 ++-- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- README.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 13a2f21..dabf454 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,12 +1,12 @@ { "name": "onesignal", - "description": "OneSignal onboarding skills for coding agents: install the OneSignal SDK, provision push credentials, and send a test notification to your device.", + "description": "OneSignal onboarding for coding agents: install the OneSignal SDK, set up your push credentials, and verify that a real notification reaches your device.", "owner": { "name": "OneSignal", "url": "https://onesignal.com" }, "plugins": [ { "name": "onesignal", "source": "./", - "description": "OneSignal onboarding & activation skills" + "description": "OneSignal onboarding for coding agents: install the OneSignal SDK, set up your push credentials, and verify that a real notification reaches your device." } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 2261134..527f37f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "onesignal", "displayName": "OneSignal", - "description": "OneSignal onboarding & activation skills: install and initialize the SDK, provision your app and push credentials, and verify real delivery.", + "description": "OneSignal onboarding for coding agents: install the OneSignal SDK, set up your push credentials, and verify that a real notification reaches your device.", "version": "1.1.1", "author": { "name": "OneSignal", diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 3f0606d..ab1766f 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "onesignal", "version": "1.1.1", - "description": "OneSignal onboarding & activation skills: install and initialize the SDK, provision your app and push credentials, and verify real delivery.", + "description": "OneSignal onboarding for coding agents: install the OneSignal SDK, set up your push credentials, and verify that a real notification reaches your device.", "author": { "name": "OneSignal", "url": "https://onesignal.com" diff --git a/README.md b/README.md index 21dcae2..207eba5 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ plugin, then add + install it. { "name": "onesignal", "source": "./onesignal-agent-plugin", - "description": "OneSignal onboarding & activation skills" + "description": "OneSignal onboarding for coding agents: install the OneSignal SDK, set up your push credentials, and verify that a real notification reaches your device." } ] } From 2d4bccb7146aa2086810ae097cb906aa479923e1 Mon Sep 17 00:00:00 2001 From: sherwinski Date: Fri, 9 Oct 2026 17:42:08 -0700 Subject: [PATCH 5/5] docs: [SDK-5456] restore the trigger phrases in each skill description Both hosts pick a skill from its `description` (Agent Skills spec; OpenAI and Anthropic skill docs). The shorter descriptions kept the summary but dropped the "when to use" text, so a prompt such as "why isn't my push arriving" no longer matched one skill. Each description now keeps the one-line summary first, for the listing card, and adds a "Use when" sentence with the trigger phrases after it. The verify description also loses a `: ` inside the plain scalar, which libyaml rejects as a mapping value. --- skills/credentials/SKILL.md | 2 +- skills/setup/SKILL.md | 2 +- skills/verify/SKILL.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/credentials/SKILL.md b/skills/credentials/SKILL.md index 46f0b10..f21ff37 100644 --- a/skills/credentials/SKILL.md +++ b/skills/credentials/SKILL.md @@ -1,6 +1,6 @@ --- name: credentials -description: Upload your APNs .p8 key, Firebase FCM service-account JSON, or web Site URL to OneSignal, and get guided setup for Safari certs, email SPF/DKIM/DMARC DNS records, and SMS sender registration. +description: Upload your APNs .p8 key, Firebase FCM service-account JSON, or web Site URL to OneSignal, and get guided setup for Safari certs, email SPF/DKIM/DMARC DNS records, and SMS sender registration. Use when the user asks to "set up APNs", "add my .p8", "connect Firebase / FCM", "upload push credentials", "configure email domain / DNS", or "set up SMS", asks why Android or iOS push is failing, says push is not delivering after the SDK install, or when another OneSignal skill reports that a platform is missing credentials. argument-hint: "[platform=ios|android|web|email|sms] [app=]" --- diff --git a/skills/setup/SKILL.md b/skills/setup/SKILL.md index ef960ea..21c8885 100644 --- a/skills/setup/SKILL.md +++ b/skills/setup/SKILL.md @@ -1,6 +1,6 @@ --- name: setup -description: Set up OneSignal in your codebase by asking "set up OneSignal". Detects the platform/framework from your project, guides you through uploading push credentials, installs and sets up the SDK, then hands off to the verify skill. +description: Set up OneSignal in your codebase by asking "set up OneSignal". Detects the platform/framework from your project, guides you through uploading push credentials, installs and sets up the SDK, then hands off to the verify skill. Use when a developer wants to add, install, integrate, or initialize the OneSignal SDK in a web, iOS, Android, React Native, Expo, Flutter, Cordova/Ionic/Capacitor, or Unity project, says "add push notifications", "install the OneSignal SDK", "integrate OneSignal", or "onboard onto OneSignal", or opens a fresh project with no OneSignal present. Supports one-command invocation, for example "/onesignal:setup app=". argument-hint: app= --- diff --git a/skills/verify/SKILL.md b/skills/verify/SKILL.md index 506f79a..b9023d4 100644 --- a/skills/verify/SKILL.md +++ b/skills/verify/SKILL.md @@ -1,6 +1,6 @@ --- name: verify -description: Verify that your OneSignal integration works end to end: builds/runs your app, waits for the first real device subscription to register, sends a real test push, and confirms server-side delivery. +description: Verify that your OneSignal integration works end to end — builds/runs your app, waits for the first real device subscription to register, sends a real test push, and confirms server-side delivery. Use after the setup or credentials skills have run, or when the user asks to "verify OneSignal works", "test push delivery", "prove the integration works", "confirm the device registered", or "send myself a test notification", asks why a notification is not arriving, or is debugging an install that looks complete but delivers nothing. Does not install the SDK or upload credentials; routes to those skills when they are missing. argument-hint: "[app=]" ---