Post-launch Skill · Revamp Dossier

ad-complianceReactive Meta policy engine — diagnoses a rejection, proposes a fix, and (only when explicitly requested) pre-screens ad copy in Audit mode.

Owner: Reactive — fires only after a Meta ad rejection; operator-invoked via /ad-comply · Asel · 2026-06-11
What it does

Ad-compliance is reactive. It fires only after Meta (Meta Platforms, the company behind Facebook and Instagram) rejects an ad. Do not run it pre-emptively on new scripts — pre-submission scanning kills creative freedom. Once a rejection lands, the skill pulls the rejection reason and ad copy, maps the root cause using a deterministic decision tree, and produces an explicit fix for every violation. It also generates a ready-to-use appeal template when the rejection is a false positive. The operator invokes it via /ad-comply.

One narrow exception exists: Audit mode runs Steps 1–7 (the full policy checklist) on ad copy before submission — but only when Asel explicitly requests it. It is not part of the creative pipeline and is never auto-triggered. Note that health-claim sensitivity (Tier 1 banned words — "cure," "treat," "clinically proven") is highest-risk in wellness niches and directly ties back to the hook frameworks covered in ad-hook-niche-health.

01 Model routing — which task runs on which model

All model calls go through OpenRouter and are logged with model ID, provider, and cost before the agent_run row closes. Deterministic scanning never touches a language model — the model only reasons over the bounded shortlist the scan emits.

TaskModelWhy
Prohibited-content scan (Step 1), personal-attributes scan (Step 2), banned-word/phrase scan (Step 4) — all thirteen prohibited categories plus the full tier table Plain code — no language model Deterministic-first rule. Term matching against a fixed vocabulary emits a bounded shortlist (hits with location + context). A language model adds latency and cost and cannot improve on exact-match logic. The model reasons over this shortlist, not instead of it.
Rejection data ingest from Meta Ads Manager via MCP (Model Context Protocol) — pulling the ad ID, rejection code, and ad copy as structured fields claude-haiku-4-5 (Haiku 4.5) via OpenRouter Pure structured extraction — no synthesis, no judgment. Cheapest capable model. Haiku 4.5 handles the mechanical pull so Opus 4.8 receives clean, pre-structured input before beginning diagnosis.
Root-cause diagnosis — mapping the rejection reason to the decision tree, evaluating framing context for personal-attribute violations, identifying all violations from the scan shortlist (Step 8A/8B) claude-opus-4-8 (Opus 4.8) via OpenRouter Legal and brand risk. A wrong diagnosis sends a non-compliant ad back to Meta or, worse, triggers an account review. Consequence-routed to the highest reasoning tier. Every call logged to the audit trail.
Compliant rewrite — producing revised primary text (PT), headline, and description that pass all checks claude-opus-4-8 (Opus 4.8) via OpenRouter Same consequence reasoning: an incorrect rewrite re-triggers rejection or produces a weaker creative. Full reasoning capacity required. The rewrite must preserve the voice-book signature patterns from the Expert Voice Book while satisfying Meta policy.
Appeal template generation (Step 9) — drafting the factual, policy-cited appeal for false-positive rejections claude-opus-4-8 (Opus 4.8) via OpenRouter Appeals that misquote policy or mischaracterise the ad copy worsen account standing. Consequence-routed high. Opus 4.8 quotes exact compliant language, cites specific Meta policy sections, and frames the case without overstatement.
Compliance Scorecard assembly (Step 7) — structuring the binary check results into a single summary with overall verdict claude-sonnet-4-6 (Sonnet 4.6) via OpenRouter Structured summary of deterministic results. Lower synthesis load than diagnosis or rewrite; no legal risk at this stage. Sonnet 4.6 is sufficient and cheaper than Opus 4.8 for this task.
Reconciliation note for operator

The dossier context pack's standard model menu (plain code / Opus 4.8 / Fable 5) does not enumerate Haiku 4.5 or Sonnet 4.6. This dossier follows the skill source, which specifies both. Flag to operator: confirm whether Haiku 4.5 and Sonnet 4.6 are approved additions to the SKL OpenRouter account routing table.

02 The spec

What goes in, what comes out, and the HALT conditions that prevent a silent failure.

Inputs

InputSourceRequired
Rejection reason / code Meta Ads Manager via MCP (Model Context Protocol), or the operator reports it directly YES — the skill cannot diagnose without it
Rejected ad copy (primary text, headline, description) Meta Ads Manager via MCP, or operator-supplied YES
Video script (if the rejected ad includes a video) creative_scripts Supabase view (source of record); local .md export as fallback only Recommended — needed to diagnose script-level violations
Landing page (LP) URL expert_profile Supabase view, status = 'current' YES — Meta checks the LP; a compliant ad paired with a non-compliant LP still gets rejected
Expert niche expert_profile Supabase view, status = 'current' YES — compliance rules vary critically by vertical (health vs business vs financial)
HALT conditions

If expert_namespace is not provided → HALT. If expert_profile returns no status='current' row → HALT. If Supabase is unreachable at startup → HALT. In all three cases: set agent_run.status = 'halted', write a plain-English status_detail, and stop. Never treat an infrastructure failure as an empty result or a clean diagnosis.

Diagnosis + fix report

Primary output — Post-rejection mode (default trigger). Produced by Steps 8A–8B after plain-code scans complete.
FieldWhat it means
root_causeThe single most likely cause of rejection, mapped from the decision-tree (Step 8A). Written in plain English. Example: "Personal attributes — second-person address combined with a negative financial state ('Are you broke?') violates Meta's personal-attributes policy."
confidenceHIGH / MED / LOW. HIGH means the rejection reason maps cleanly to one decision-tree entry with a clear text match. LOW means the rejection code is ambiguous (e.g. code 2490427 — general disapproval) and multiple root causes are possible.
violations_foundOrdered list of every violation found in the full re-scan (Steps 1–6). Each entry names the step, the category (e.g. "Step 2 — Personal Attributes"), the exact offending text with its location (primary text / headline / video script timestamp), and the relevant tier (Tier 1 = instant rejection, Tier 2, etc.).
fixesOne explicit fix per violation: the original text, the revised text, the technique applied (e.g. Aspiration Framing, Third-Person Story), and the reason the fix resolves the violation. Fixes are in priority order — Tier 1 and Tier 2 violations first.
appeal_decisionYES / NO. YES only if the rejection is a false positive (the ad copy was genuinely compliant and Meta's automated review made an error) or clearly borderline. Otherwise the verdict is NO — fix first, create a new ad, never edit the rejected ad in place (in-place editing triggers a re-review flag).
appeal_templateOnly present when appeal_decision = YES. A ready-to-paste appeal that quotes the exact compliant language used, references the specific Meta policy section, and describes what the ad does NOT contain. One of five template types from Step 9 (Personal Attributes / Health / Before-and-After / Income / Generic).
wait_recommendationHow long to wait before resubmitting: immediate if this is a first-offense fix; 24 hours recommended as a default; 48 hours if the account has prior violation history. This is a precautionary buffer, not a Meta-enforced rule.

Compliance Scorecard

Audit mode only — produced when Asel explicitly requests a pre-submission compliance check (not part of the creative pipeline). Output of Steps 1–7.
FieldWhat it means
prohibited_contentCLEAR or X violations (one line per category from Meta's 13 prohibited categories).
personal_attributesCLEAR or X violations. The most common rejection reason — "you" + negative attribute in any combination.
restricted_contentCOMPLIANT or action required (e.g. age-gating needed, disclaimer required).
special_ad_categoryNONE or DECLARED: [category]. For IDA (income/business coaching) this is typically NONE unless financial products are referenced.
banned_words_by_tierCLEAN or X found. Breakdown by tier: Tier 1 (instant rejection — health claims), Tier 2 (instant rejection — income claims), Tier 3 (high risk — false urgency/scarcity), Tier 4 (Meta platform references), Tier 5 (engagement bait).
landing_pageCOMPLIANT or X issues across 13 checks (functional, content match, privacy policy, terms of service, no malware, mobile-friendly, consistent offer, no misleading elements, contact info, earnings disclaimer, health disclaimer, testimonial disclaimer, no Facebook references).
before_afterCOMPLIANT / N/A / issues. Applies to transformation claims in thumbnail, video, or verbal results.
verdictCLEAR TO SUBMIT (0 issues) / SUBMIT WITH CAUTION (warnings only, no blocking violations) / FIX BEFORE SUBMITTING (1+ blocking issues) / DO NOT SUBMIT (any Tier 1/2 banned word or prohibited content found).

agent_run row (open and close)

Supabase agent_run table — opened at start, closed at end, in both Post-rejection and Audit modes.
FieldWhat it means
agent_nameAlways 'ad-compliance'.
triggered_by'operator' (user invokes /ad-comply) / 'MCP' (rejection detected via Meta Ads Manager Model Context Protocol) / 'user-report' (user describes a rejection) / 'audit-request' (Audit mode only).
expert_namespaceWhich expert this run is for — e.g. 'ida' for Amelia Fenmore.
ad_idThe Meta ad ID, if available. Used to retrieve the rejected copy via MCP.
rejection_reasonThe raw rejection reason string from Meta Ads Manager.
statusSet to 'running' at open. Updated to 'success' (all checks run, verdict issued) / 'partial' (some inputs missing, diagnosis incomplete) / 'failed' (unexpected error) / 'halted' (HALT condition met — Supabase unreachable, expert_profile missing, or expert_namespace not supplied) at close.
status_detailHuman-readable explanation for any non-success status. Also records the model used for each reasoning step and, if Sonnet 4.6 was used for the scorecard, notes this in the log.

03 Live output example representative

About this example

No eval artifacts exist for ad-compliance (the skill is reactive — it only runs when Meta rejects an ad). This example is constructed from real IDA mechanics: Amelia Fenmore is an interior-design business coach whose ads drive cold Meta traffic to a free training, which converts to booked sales calls. The primary success metric is CPBC (cost per booked call — how much it costs to get one person to book a sales call). The rejection scenario uses the most common rejection reason in the IDA niche: Personal Attributes (Meta policy category 10) — second-person address combined with a negative financial state.

REPRESENTATIVE EXAMPLE — IDA (Amelia Fenmore), Post-rejection mode, 2026-06-11. Constructed from real IDA niche mechanics. Badge: b-rep.
=== AGENT RUN OPEN ===
agent_name:       ad-compliance
triggered_by:     operator
expert_namespace: ida
ad_id:            120215493827640000
rejection_reason: "This ad can't run because it implies personal attributes about people who see it"
started_at:       2026-06-11T09:14:22Z
status:           running
run_id:           acr-20260611-0914

=== STEP 8A: REJECTION REASON DIAGNOSIS ===

Rejection reason: "This ad can't run because it implies personal attributes..."
Decision tree mapping: PERSONAL ATTRIBUTES (Step 2 — #1 rejection reason)
Confidence: HIGH

The rejection reason maps cleanly to Meta's personal-attributes category. This is the most
common rejection in the IDA niche. Running full scan now to locate every violation.

=== STEPS 1–6: FULL RE-SCAN ===

[Plain code scan output — bounded shortlist for model reasoning]

Step 1 — Prohibited Content:        CLEAR (all 13 categories)
Step 3 — Restricted Content:        COMPLIANT — income/business niche, no Special Ad Category required
Step 5 — Landing Page (LP):         CLEAR (HTTPS confirmed, earnings disclaimer present at footer,
                                    "results not typical" near testimonials, no FB logo found)
Step 6 — Before/After:              N/A (no transformation images in this creative)

Step 2 — Personal Attributes:       2 VIOLATIONS FOUND
  [V1] Primary text, line 1:
       "Are you still trading your time for $3K design projects when your customers
        have $30K budgets?"
       Rule triggered: "you" + negative financial state ("still trading time for $3K")
       — asserts the viewer is in a financially inferior position. Tier: instant rejection.

  [V2] Primary text, line 4:
       "If you're struggling to raise your fees, here's why..."
       Rule triggered: "If you're struggling with [X]" — banned pattern regardless of niche.
       Tier: instant rejection.

Step 4 — Banned Words:              TIER 2 — 1 item
  [B1] Primary text, line 3:
       "guaranteed income growth" — Tier 2 banned phrase (income claims).
       Instant rejection.

=== ROOT CAUSE SUMMARY ===

Primary root cause:  Personal Attributes — V1 and V2 above (HIGH confidence)
Secondary violation: Tier 2 income claim — B1 above
Total blocking violations: 3
Verdict: FIX BEFORE SUBMITTING (do not appeal without fixing first)

=== FIX PROTOCOL (STEP 8B) ===

Fix F1 — resolves V1
  Original:  "Are you still trading your time for $3K design projects when your customers
              have $30K budgets?"
  Technique: Aspiration Framing (forward-looking, removes viewer-negative assertion)
  Revised:   "What would change if your next interior design project paid $30K instead
              of $3K?"
  Why:       Removes "you" + negative state. The revised version invites curiosity
             (aspiration) without asserting the viewer is currently underpaid.

Fix F2 — resolves V2
  Original:  "If you're struggling to raise your fees, here's why..."
  Technique: Third-Person Story (shifts struggle to a named character, not the viewer)
  Revised:   "Amelia charged $3K for years before she understood what was holding
              her pricing back."
  Why:       Completely removes second-person address. Amelia's story creates the
             same emotional bridge without asserting anything about the viewer.

Fix F3 — resolves B1
  Original:  "guaranteed income growth"
  Revised:   "a path to consistent income growth"
  Why:       "guaranteed" is a Tier 2 banned word. "a path to" removes the guarantee
             while preserving the promise of direction and momentum.

=== APPEAL DECISION ===
Appeal: NO
Reason: All three violations are genuine policy hits — not false positives. Fix first.
Create a NEW ad using the revised copy above. Do not edit the rejected ad in place
(in-place editing triggers a re-review flag on the account).

=== WAIT RECOMMENDATION ===
Wait period: 24 hours (standard recommendation; escalate to 48h if account
has prior violation history this month).

=== FINAL CONFIRMATION ===
"Diagnostic complete. Root cause: Personal Attributes (HIGH confidence) +
Tier 2 income claim. 3 violations fixed. Create a new ad with the revised copy
above. Wait 24h before submitting. No appeal recommended."

=== AGENT RUN CLOSE ===
status:        success
status_detail: 3 violations found (V1 personal-attribute/aspiration, V2 personal-attribute/
               third-person, B1 Tier2-income). All fixed. No appeal. New ad recommended.
               Models used: Haiku 4.5 (Meta MCP ingest), Opus 4.8 (diagnosis + rewrite).
               OpenRouter cost: logged to run_id acr-20260611-0914.
How to read it: The run opens an agent_run row immediately — the run_id stamps every downstream write. The plain-code scan runs first (Steps 1–6) and emits a bounded shortlist of hits; Opus 4.8 reasons over that shortlist, not the raw ad text, to determine context and framing. Each fix names the original text, the revised text, the technique applied (Aspiration Framing / Third-Person Story / neutral replacement), and why the fix resolves the violation. The appeal decision is NO because all three violations are genuine — the rule is "fix first, appeal only for false positives." The run closes with a plain-English confirmation the operator can act on immediately. Notice the Voice Book is implicitly in play: Fix F2 uses Amelia's own story (credential-inversion pattern) because it matches her established voice — a rewrite that sounds like a different expert would fail the voice-fidelity check even if it passed Meta policy.

04 Glossary

Every abbreviation spelled out with contextual grounding. If a term appears in this dossier, it is defined here.

TermIn full / what it means
MetaMeta Platforms — the company that owns Facebook, Instagram, and the Meta Ads Manager platform. All ad rejections, policy categories, and appeal processes described in this dossier refer to Meta's advertising rules.
MCPModel Context Protocol — the integration layer that lets the agent pull structured data (ad ID, rejection code, copy) directly from Meta Ads Manager without the operator copying and pasting. Haiku 4.5 handles this ingest step.
CPBCCost Per Booked Call — how much was spent on Meta ads to get one person to book a sales call with Amelia Fenmore. The primary success metric for IDA cold traffic. Target threshold lives in the expert_profile Supabase row for IDA.
CPLCost Per Lead — how much was spent to get one person to register for the free training (the intermediate conversion before a booked call). Used as an early-signal proxy before CPBC data is available.
LPLanding Page — the web page the Meta ad sends the viewer to after they click. Meta checks the LP as part of its review — a compliant ad paired with a non-compliant LP still gets rejected.
PTPrimary Text — the main body of text shown below a Meta ad (the long-form copy visible before "See more"). Distinct from Headline (bold text above the LP URL) and Description (smaller text below the headline).
Personal AttributesMeta Policy Category 10 — Personal Attributes — the rule that prohibits any ad from asserting or implying that the viewer has specific personal characteristics (financial state, health condition, relationship status, emotional state). The most common rejection reason across all niches. Triggered by any second-person ("you"/"your") construction paired with a negative attribute.
Banned Terms (Tier 1–5)The five tiers of banned words and phrases in Meta ad copy. Tier 1: health claims ("cure", "treat", "clinically proven") — instant rejection. Tier 2: income claims ("guaranteed income", "get rich quick") — instant rejection. Tier 3: false urgency/scarcity ("last chance ever", "only X spots left" when false) — high risk. Tier 4: Meta platform references ("Facebook", "Instagram", "Meta", interface screenshots) — prohibited in ad copy. Tier 5: engagement bait ("tag a friend", "like if you agree") — prohibited. Tier 1 and 2 violations are always DO NOT SUBMIT.
Reactive vs Audit modeThe two operating modes of ad-compliance. Reactive (Post-rejection mode): the default — fires after Meta rejects an ad, runs Steps 8A and 8B (decision tree + fix protocol), then optionally Steps 1–6. Audit mode: runs Steps 1–7 on ad copy before submission — only when Asel explicitly requests it. Never auto-triggered. Never inserted into the creative pipeline.
Claim SubstantiationThe requirement that any factual claim in an ad be backed by evidence that can be produced if Meta or the FTC (Federal Trade Commission — the US consumer-protection regulator) requests it. "Clinically proven" requires a published clinical trial. "Doctor recommended" requires a documented endorsement. Student results require a contextual disclaimer ("results not typical; individual results vary"). Without substantiation, a claim is a violation.
FTCFederal Trade Commission — the US regulator responsible for advertising truth-in-advertising rules, including the income-claims and testimonials guidelines that apply to coaching offers sold to US audiences. Earnings disclaimers on the LP are required for FTC compliance, not just Meta compliance.
FDAFood and Drug Administration — the US regulator for drugs and medical devices. "FDA approved" in ad copy is a Tier 1 banned phrase unless the product actually has FDA approval. For coaching and wellness offers, FDA claims are never appropriate.
Special Ad CategoryA Meta-declared classification that limits targeting options in exchange for anti-discrimination compliance. Categories: Credit, Employment, Housing, Social Issues/Elections/Politics. Must be declared before an ad can run. For IDA (income/business coaching), this is typically NONE — but any ad that references financial products or targets job seekers may require an Employment or Credit declaration.
Safe Framing TechniquesThe five patterns that satisfy Meta's personal-attributes rule. (1) Third-Person Story: "She was struggling with..." — shifts from viewer assertion to a named character's experience. (2) First-Person Narrative: "I used to struggle with..." — the expert's own story. (3) Community Framing: "Many women find that..." — collective, not individual assertion. (4) Aspiration Framing: "Ready for financial growth?" — forward-looking, no negative state implied. (5) Discovery Framing: "Discover what changes when..." — curiosity-led, no assertion.
IDAThe expert code for Amelia Fenmore, an interior-design business coach. IDA cold Meta ads drive traffic to a free training that converts to booked sales calls (measured by CPBC). The Supabase namespace for all IDA rows is 'ida'. Note for operator: the ad-autopsy dossier expands IDA as "Interior Design Academy" — this could not be confirmed against the authoritative context pack, which defines IDA as "Amelia Fenmore — interior-design business coach." Operator to confirm the correct entity name.
Voice BookExpert Voice Book — the structured document built by ad-voice-profile that captures an expert's signature phrases, sentence rhythms, forbidden words, and proof-delivery patterns. Previously called "Layer 3 calibration" — that name is deprecated. Ad-compliance rewrites must preserve Voice Book signature patterns; a fix that passes Meta policy but sounds like a different expert fails voice-fidelity.
ad-hook-niche-healthThe health-specific hook framework skill — a companion to ad-hook-generation covering 12 frameworks (H1–H12) for health and wellness verticals. Relevant to ad-compliance because Tier 1 banned words (health claims) are most common in health-niche ads, and safe hook patterns from ad-hook-niche-health are the correct fix vocabulary for those rejections.
agent_runSupabase audit table — records every agent run. Ad-compliance opens a row at startup and closes it at completion. The row's id (run_id) stamps every Supabase write made during the run, creating a full trace from rejection to diagnosis to fix.
expert_profileSupabase view (Layer 2 adjacent) — stores the current configuration for each expert, including landing_page_url, niche, and status. Ad-compliance reads from this view — never from Drive or Fibery at runtime. If no status='current' row exists for the expert, the skill halts.
creative_scriptsSupabase view — stores the polished scripts for each creative, keyed by Fibery creative ID. Ad-compliance reads from this view when diagnosing script-level violations in a rejected video ad. Local .md exports are accepted as a fallback only.
OpenRouterOpenRouter (model routing proxy) — the API gateway through which all language model calls in this system are routed. Provides unified billing, model switching, and per-call logs (model ID, provider, cost) that feed the agent_run audit trail.
SupabaseSupabase (database platform) — the PostgreSQL-based database that hosts the SKL ad creative system data layer. Ad-compliance reads expert_profile and creative_scripts views from Supabase and writes the agent_run row.
Haiku 4.5claude-haiku-4-5 via OpenRouter — the lightweight Claude model used for structured extraction tasks (Meta MCP ingest in this skill). Cheapest capable model for mechanical data pull with no synthesis required.
Opus 4.8claude-opus-4-8 via OpenRouter — the highest-reasoning Claude model, used for consequence-routed tasks: root-cause diagnosis, compliant rewrite, and appeal-template generation. All three carry legal and brand risk if wrong.
Sonnet 4.6claude-sonnet-4-6 via OpenRouter — the mid-tier Claude model, used for Compliance Scorecard assembly (structured summary of binary check results; lower synthesis load, no legal risk at this stage).
MLMMulti-Level Marketing — a business model flagged by Meta under "Unacceptable Business Practices." MLM language in ad copy (downline recruitment, network pay-per-recruit framing) triggers a rejection that is rarely worth appealing — a full messaging overhaul is required.
FiberyFibery (project management and system of record) — the creative-entity database that tracks CREATIVE and HOOK entities, their production status, and their Meta performance data. Ad-compliance does not write to Fibery directly — it reads the video script via the creative_scripts Supabase view, which is populated from Fibery by Hermes agents.
HermesHermes (autonomous agent layer) — the always-on agent harness that maintains the Supabase data layer. Relevant to ad-compliance in that creative_scripts and expert_profile views are kept current by Hermes sync jobs — ad-compliance reads these views and relies on them being fresh.