Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
name: Validate plugin

on:
workflow_dispatch:
pull_request:
push:
branches: [main]
release:
types: [published]
schedule:
- cron: "17 9 * * 1"

permissions:
contents: read
Expand Down Expand Up @@ -51,3 +56,35 @@ jobs:

- name: Test utility fixture contracts
run: python scripts/test_fixtures.py

- name: Test Sent API contract regressions
run: python scripts/test_contracts.py

live-contract-and-routing:
if: github.event_name == 'schedule' || github.event_name == 'release' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SENT_ROUTING_EVAL_MODEL: ${{ vars.SENT_ROUTING_EVAL_MODEL || 'gpt-5-mini' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: pip
cache-dependency-path: requirements-dev.txt

- name: Install validators
run: python -m pip install -r requirements-dev.txt

- name: Compare live Sent OpenAPI with manifest
run: python scripts/check_live_contract.py

- name: Run model-backed routing evaluation
if: env.OPENAI_API_KEY != ''
run: python scripts/run_model_routing_eval.py

- name: Explain skipped model evaluation
if: env.OPENAI_API_KEY == ''
run: echo "OPENAI_API_KEY is not configured; live contract drift still ran, but model routing evaluation was skipped."
12 changes: 3 additions & 9 deletions adapter-sources/claude/commands/mdr-analyze.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Analyze Sent Message Delivery Reports (MDRs) across SMS, WhatsApp, and RCS to find where a funnel is leaking
description: Analyze Sent message-delivery performance
---

Invoke the `messaging-performance-analyzer` skill.
Invoke the `messaging-performance-analyzer` skill with the user's request unchanged:

Begin by pinning the question. Ask:
1. Which channel is this about — SMS, WhatsApp, RCS, or a cross-channel comparison?
2. What's the specific concern? ("delivery dropped today", "this template underperforms in Brazil", "RCS not reaching T-Mobile recipients", "leads aren't replying")
3. The cohort: which template / campaign / agent, which country/countries, which tenant(s), which time window?
4. The data source: CSV/JSON dump, paste, log file path, or a database the user can query?

If the question is too vague to answer (e.g. "how are we doing"), narrow it before pulling data. Always require a defined cohort and a named channel. For RCS funnels, also ask whether SMS fallback is in play so the analysis can separate it.
$ARGUMENTS
13 changes: 3 additions & 10 deletions adapter-sources/claude/commands/rcs-onboard.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Create + verify an RCS Business Messaging (RBM) agent for sending RCS via Sent, including capability + fallback decisions
description: Prepare an RCS launch through Sent
---

Invoke the `rcs-agent-onboarding` skill.
Invoke the `rcs-agent-onboarding` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh agent creation, or are you debugging a stuck verification / launch review?
2. The tenant's public brand identity (display name, logo, brand color) and verified domains
3. The use case (transactional, OTP, customer care, promotional, multi-use)
4. Which capabilities will the agent actually use (suggested replies, suggested actions, rich cards, carousel, attachments)?
5. The SMS fallback policy when a recipient isn't RCS-capable (`sms` via the same Sender Profile, `none`, or application-routed)

Then walk the agent identity setup, capability declaration, verification + launch-review path, and per-carrier rollout expectations. Flag anything that mismatches the tenant's public brand or requires re-review.
$ARGUMENTS
13 changes: 3 additions & 10 deletions adapter-sources/claude/commands/sender-plan.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Plan multi-tenant architecture around Sent's Sender Profile — data model, channel routing across SMS/WhatsApp/RCS, rate limits, lifecycle
description: Design Sent Sender Profile architecture
---

Invoke the `sender-profile-architect` skill.
Invoke the `sender-profile-architect` skill with the user's request unchanged:

Begin by asking:
1. Which channels does the tenant need (SMS, WhatsApp, RCS, or a mix)?
2. Tenant scale — current and 12-month projection (10? 1,000? 100,000?)
3. Isolation requirements — any regulated tenants (PHI, government, data-residency)?
4. Existing stack — datastore, queue, cache, language/framework
5. The specific design question — data model, webhook routing, rate limits, or lifecycle?

Then walk the Sender Profile framing and produce a concrete model / sequence / state-machine sketch tailored to the answers. Recommend pooled by default; recommend silos only when the answers justify them. Reference the channel-specific onboarding skills (`sms-10dlc-registration`, `waba-embedded-signup`, `rcs-agent-onboarding`) for the parts that fall outside the architecture concern.
$ARGUMENTS
6 changes: 3 additions & 3 deletions adapter-sources/claude/commands/sent.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Sent meta dispatcher — routes to the right SMS/WhatsApp/RCS skill on Sent
description: Route a request through the Sent skill set
---

Invoke the `sent` skill to triage which Sent workflow the user wants and route to the corresponding direct-operation or specialist skill.
Invoke the `sent` skill with the user's request unchanged:

Ask the clarifying questions in that skill before routing.
$ARGUMENTS
13 changes: 3 additions & 10 deletions adapter-sources/claude/commands/sms-register.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Register a brand + campaign with The Campaign Registry (TCR) for 10DLC A2P SMS on Sent
description: Prepare a Sent US 10DLC registration
---

Invoke the `sms-10dlc-registration` skill.
Invoke the `sms-10dlc-registration` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh registration, or are you debugging a rejection / low vetting score?
2. The legal entity that's sending (parent company vs sub-brand) and its strongest external identifier (EIN, DUNS, GIIN, LEI)
3. The specific use case for this campaign — transactional notifications, 2FA, customer care, marketing, mixed?
4. Expected volume per day and which carriers (T-Mobile / AT&T / Verizon / all)?
5. The opt-in mechanism (how recipients agreed to receive these messages)

Then walk the Brand → Campaign sequence, pick the narrowest accurate TCR use case, produce sample messages that match production traffic and include opt-out language, and call out any attributes likely to trigger a downgrade.
$ARGUMENTS
12 changes: 3 additions & 9 deletions adapter-sources/claude/commands/template-ui.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Design and implement the tenant-facing UI for submitting WhatsApp templates to Sent
description: Design a Sent template-builder interface
---

Invoke the `template-builder-ui` skill.
Invoke the `template-builder-ui` skill with the user's request unchanged:

Begin by asking:
1. The frontend framework (React, Vue, Svelte, etc.) and existing design system
2. Whether the editor is a greenfield build or extending something
3. Which validation layers already exist on the backend (so the UI doesn't duplicate or conflict)
4. Realtime channel availability (WebSocket, SSE) for template-status updates

Then walk the editor anatomy (category first, then components, then live preview), produce component scaffolds, and surface the policy rules the UI must encode. Cross-reference `waba-template-author` for category rules.
$ARGUMENTS
12 changes: 3 additions & 9 deletions adapter-sources/claude/commands/waba-auth.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Implement Meta's WhatsApp Embedded Signup flow end-to-end (or debug a stuck one)
description: Guide WABA onboarding through Sent
---

Invoke the `waba-embedded-signup` skill.
Invoke the `waba-embedded-signup` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh integration or debugging an existing one?
2. Tech Provider / Solution Partner status with Meta?
3. Existing Meta app state — products added (WhatsApp, FBL)? `config_id` created? Redirect URIs allowlisted?
4. If debugging, which step is stuck? (Dialog won't open, code exchange failing, webhooks not firing, etc.)

Then walk the prerequisite checklist, the launch + exchange + register + subscribe sequence, and persist the SPS state at each step. For debugging, jump to the "Common Stuck States" table and triage from there.
$ARGUMENTS
12 changes: 3 additions & 9 deletions adapter-sources/claude/commands/waba-template.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Author a WhatsApp Business API template and classify it as utility, marketing, or authentication per Meta's policy
description: Author a WhatsApp template for Sent
---

Invoke the `waba-template-author` skill.
Invoke the `waba-template-author` skill with the user's request unchanged:

Begin by asking the user:
1. The use case in one sentence ("After a customer pays, confirm the order…")
2. The recipient's relationship to the event (did they trigger it, or is the business reaching out cold?)
3. Whether this is a code / OTP (authentication template) or a regular template
4. The target language (BCP-47 code, e.g. `en_US`, `pt_BR`)

Then walk the decision tree, draft the components, and produce a submission-ready Cloud API payload. Flag any wording or imagery that's likely to flip the category at Meta's review.
$ARGUMENTS
12 changes: 3 additions & 9 deletions claude-plugins/sent/.claude/commands/mdr-analyze.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Analyze Sent Message Delivery Reports (MDRs) across SMS, WhatsApp, and RCS to find where a funnel is leaking
description: Analyze Sent message-delivery performance
---

Invoke the `messaging-performance-analyzer` skill.
Invoke the `messaging-performance-analyzer` skill with the user's request unchanged:

Begin by pinning the question. Ask:
1. Which channel is this about — SMS, WhatsApp, RCS, or a cross-channel comparison?
2. What's the specific concern? ("delivery dropped today", "this template underperforms in Brazil", "RCS not reaching T-Mobile recipients", "leads aren't replying")
3. The cohort: which template / campaign / agent, which country/countries, which tenant(s), which time window?
4. The data source: CSV/JSON dump, paste, log file path, or a database the user can query?

If the question is too vague to answer (e.g. "how are we doing"), narrow it before pulling data. Always require a defined cohort and a named channel. For RCS funnels, also ask whether SMS fallback is in play so the analysis can separate it.
$ARGUMENTS
13 changes: 3 additions & 10 deletions claude-plugins/sent/.claude/commands/rcs-onboard.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Create + verify an RCS Business Messaging (RBM) agent for sending RCS via Sent, including capability + fallback decisions
description: Prepare an RCS launch through Sent
---

Invoke the `rcs-agent-onboarding` skill.
Invoke the `rcs-agent-onboarding` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh agent creation, or are you debugging a stuck verification / launch review?
2. The tenant's public brand identity (display name, logo, brand color) and verified domains
3. The use case (transactional, OTP, customer care, promotional, multi-use)
4. Which capabilities will the agent actually use (suggested replies, suggested actions, rich cards, carousel, attachments)?
5. The SMS fallback policy when a recipient isn't RCS-capable (`sms` via the same Sender Profile, `none`, or application-routed)

Then walk the agent identity setup, capability declaration, verification + launch-review path, and per-carrier rollout expectations. Flag anything that mismatches the tenant's public brand or requires re-review.
$ARGUMENTS
13 changes: 3 additions & 10 deletions claude-plugins/sent/.claude/commands/sender-plan.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Plan multi-tenant architecture around Sent's Sender Profile — data model, channel routing across SMS/WhatsApp/RCS, rate limits, lifecycle
description: Design Sent Sender Profile architecture
---

Invoke the `sender-profile-architect` skill.
Invoke the `sender-profile-architect` skill with the user's request unchanged:

Begin by asking:
1. Which channels does the tenant need (SMS, WhatsApp, RCS, or a mix)?
2. Tenant scale — current and 12-month projection (10? 1,000? 100,000?)
3. Isolation requirements — any regulated tenants (PHI, government, data-residency)?
4. Existing stack — datastore, queue, cache, language/framework
5. The specific design question — data model, webhook routing, rate limits, or lifecycle?

Then walk the Sender Profile framing and produce a concrete model / sequence / state-machine sketch tailored to the answers. Recommend pooled by default; recommend silos only when the answers justify them. Reference the channel-specific onboarding skills (`sms-10dlc-registration`, `waba-embedded-signup`, `rcs-agent-onboarding`) for the parts that fall outside the architecture concern.
$ARGUMENTS
6 changes: 3 additions & 3 deletions claude-plugins/sent/.claude/commands/sent.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: Sent meta dispatcher — routes to the right SMS/WhatsApp/RCS skill on Sent
description: Route a request through the Sent skill set
---

Invoke the `sent` skill to triage which Sent workflow the user wants and route to the corresponding direct-operation or specialist skill.
Invoke the `sent` skill with the user's request unchanged:

Ask the clarifying questions in that skill before routing.
$ARGUMENTS
13 changes: 3 additions & 10 deletions claude-plugins/sent/.claude/commands/sms-register.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
---
description: Register a brand + campaign with The Campaign Registry (TCR) for 10DLC A2P SMS on Sent
description: Prepare a Sent US 10DLC registration
---

Invoke the `sms-10dlc-registration` skill.
Invoke the `sms-10dlc-registration` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh registration, or are you debugging a rejection / low vetting score?
2. The legal entity that's sending (parent company vs sub-brand) and its strongest external identifier (EIN, DUNS, GIIN, LEI)
3. The specific use case for this campaign — transactional notifications, 2FA, customer care, marketing, mixed?
4. Expected volume per day and which carriers (T-Mobile / AT&T / Verizon / all)?
5. The opt-in mechanism (how recipients agreed to receive these messages)

Then walk the Brand → Campaign sequence, pick the narrowest accurate TCR use case, produce sample messages that match production traffic and include opt-out language, and call out any attributes likely to trigger a downgrade.
$ARGUMENTS
12 changes: 3 additions & 9 deletions claude-plugins/sent/.claude/commands/template-ui.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Design and implement the tenant-facing UI for submitting WhatsApp templates to Sent
description: Design a Sent template-builder interface
---

Invoke the `template-builder-ui` skill.
Invoke the `template-builder-ui` skill with the user's request unchanged:

Begin by asking:
1. The frontend framework (React, Vue, Svelte, etc.) and existing design system
2. Whether the editor is a greenfield build or extending something
3. Which validation layers already exist on the backend (so the UI doesn't duplicate or conflict)
4. Realtime channel availability (WebSocket, SSE) for template-status updates

Then walk the editor anatomy (category first, then components, then live preview), produce component scaffolds, and surface the policy rules the UI must encode. Cross-reference `waba-template-author` for category rules.
$ARGUMENTS
12 changes: 3 additions & 9 deletions claude-plugins/sent/.claude/commands/waba-auth.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Implement Meta's WhatsApp Embedded Signup flow end-to-end (or debug a stuck one)
description: Guide WABA onboarding through Sent
---

Invoke the `waba-embedded-signup` skill.
Invoke the `waba-embedded-signup` skill with the user's request unchanged:

Begin by asking:
1. Is this a fresh integration or debugging an existing one?
2. Tech Provider / Solution Partner status with Meta?
3. Existing Meta app state — products added (WhatsApp, FBL)? `config_id` created? Redirect URIs allowlisted?
4. If debugging, which step is stuck? (Dialog won't open, code exchange failing, webhooks not firing, etc.)

Then walk the prerequisite checklist, the launch + exchange + register + subscribe sequence, and persist the SPS state at each step. For debugging, jump to the "Common Stuck States" table and triage from there.
$ARGUMENTS
12 changes: 3 additions & 9 deletions claude-plugins/sent/.claude/commands/waba-template.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
---
description: Author a WhatsApp Business API template and classify it as utility, marketing, or authentication per Meta's policy
description: Author a WhatsApp template for Sent
---

Invoke the `waba-template-author` skill.
Invoke the `waba-template-author` skill with the user's request unchanged:

Begin by asking the user:
1. The use case in one sentence ("After a customer pays, confirm the order…")
2. The recipient's relationship to the event (did they trigger it, or is the business reaching out cold?)
3. Whether this is a code / OTP (authentication template) or a regular template
4. The target language (BCP-47 code, e.g. `en_US`, `pt_BR`)

Then walk the decision tree, draft the components, and produce a submission-ready Cloud API payload. Flag any wording or imagery that's likely to flip the category at Meta's review.
$ARGUMENTS
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Restate the user’s exact question as a measurable comparison. “WhatsApp is b

Capture these dimensions before calculating anything: profile or sender identity, template ID/name, channel, country, send window, recipient segment, and whether fallback or multi-channel broadcast was requested.

**Example.** If a user says “RCS fallback stopped working,” define the cohort as messages sent with `channel: ["rcs", "sms"]` during the affected window, then compare RCS statuses, SMS fallback statuses, and duplicate recipient/channel pairs separately.
**Example.** If a user says “RCS fallback stopped working,” define the cohort as sends that omitted `channel` or used `channel: ["sent"]`, then compare the selected `payload.channel` and message activities. Analyze any explicit multi-channel arrays separately as broadcasts.

### 2. Build cohorts from Sent message IDs

Expand Down Expand Up @@ -79,7 +79,7 @@ SMS, WhatsApp, and RCS fail differently. Do not average them together unless the
|---|---|---|
| SMS | Country, sender/profile, 10DLC campaign, opt-out, carrier family | Compliance status, brand/campaign readiness, opt-out logs, throughput patterns. |
| WhatsApp | Template, language, category, recipient country, quality/tier symptoms | Template status, read receipts, conversation window, Meta-side errors if present. |
| RCS | Agent readiness, fallback behavior, capability gaps, rich content rendering | Sent RCS setup status, fallback SMS results, capability/error details if present. |
| RCS | Agent readiness, automatic routing, pinned-channel failures, text/suggestion-chip rendering | Sent RCS setup status, selected route, and exact activity/error details. |

### 6. Quantify impact before recommending fixes

Expand All @@ -101,7 +101,7 @@ Do not label a campaign “carrier filtered” from a small sample without compa

Do not treat `READ` as a universal stage. Sent documents read receipts for WhatsApp and RCS; SMS generally does not support read receipts.

Do not collapse RCS fallback into SMS delivery. For `channel: ["rcs", "sms"]`, count RCS attempts and SMS attempts separately, then report recipient-level success if the user asks for it.
Do not mistake broadcast for fallback. Omitted `channel` or `["sent"]` enables automatic routing; one explicit channel pins delivery; multiple explicit values create separate messages. Count every returned `message_id` once and report the selected channel.

## Verification checklist

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ If `DELIVERED` is healthy and `READ` is low across all cohorts, the cause is alm

### Symptom: RCS funnel "looks broken"

RCS is two funnels stitched together. Capability check happens before delivery; most "RCS broken" reports are actually "the audience isn't RCS-capable."
RCS routing and delivery are separate stages. Capability selection happens before delivery; many "RCS broken" reports are audiences that were not routed to RCS.

- If the Sender Profile uses fallback (`"channel": ["rcs", "sms"]`), the SMS fallback leg has its own `message_id` and its own lifecycle. Count separately. Never roll fallback SMS into RCS delivery.
- Omitted `channel` or `["sent"]` enables automatic routing. Inspect the returned message record and `payload.channel` to see what Sent selected.
- `["rcs"]` pins the send to RCS and is the cleanest cohort for isolating an RCS launch or payload problem.
- Multiple explicit channels are broadcast and create separate message IDs. Count them separately and never call one leg fallback.
- Per-carrier RCS approval is real — an agent can be launched on one carrier and not on another. Symptoms scoped to one carrier point at agent state; hand off to `rcs-agent-onboarding`.

## Cross-skill handoff matrix
Expand Down
Loading