# Marketing Asset QA Pipeline — System Spec
**Version:** 1.0  
**Authors:** ARIA + loewe (_louveh_)  
**Date:** 2026-02-23  
**Status:** Approved for Implementation

---

## Overview

A two-agent adversarial pipeline for evaluating AI-generated marketing assets before delivery. Inspired by GAN architecture: a Generator produces assets, a Reviewer evaluates them with structured skepticism. The loop runs until the asset passes all layers or the iteration limit is reached.

**Core principle:**
> The Reviewer is always skeptical. Its job is not to find reasons to pass an asset — it is to find every reason to fail it. Only when it cannot find a valid reason to fail does it pass.

---

## System Architecture

```
[GENERATOR]
    ↓ produces Asset Packet
[LAYER 1] Hard Failure Detection
    ↓ pass
[LAYER 2] Brand Compliance
    ↓ pass
[LAYER 3] Aesthetic Quality
    ↓ pass
[LAYER 4] Content Relevance
    ↓ pass
[LAYER 5] Platform Fit
    ↓ pass
[DELIVER to user]

Any layer fail → structured critique → back to Generator
Max 3–5 iterations → human escalation
```

---

## The Asset Packet

The Generator produces this packet. It travels through all layers unchanged. The Generator cannot rewrite the brief mid-loop to match what it produced.

```json
{
  "image": "<file path or base64>",
  "product": "Alignly",
  "asset_type": "<declared by Generator>",
  "platform": "Instagram Stories",
  "brief": {
    "subject": "team celebrating a hire",
    "setting": "modern office",
    "key_message": "Your people, organized.",
    "audience": "HR managers",
    "cta": "Try Alignly free"
  },
  "generation_attempt": 1
}
```

---

## Reviewer Independence Rule

The Reviewer **never trusts the Generator's self-report.**

- Generator declares `asset_type` as a hint only
- Reviewer independently classifies the asset (Step 0 of Layer 1)
- If Generator's declaration contradicts Reviewer's classification → flag logged
- Repeated mismatches in a session → escalate

The Reviewer is adversarial by design. Independence must be structural, not just instructional.

---

## LAYER 1 — Hard Failure Detection

**Question:** *Is this a valid, usable asset?*  
**Type:** Binary pass/fail — instant reject on any failure  
**Vision model:** Only if Layer A passes

### Step 0 — Independent Asset Classification
Before any checks, Reviewer independently determines:
- Are humans/faces present?
- Is text present?
- Is a logo/brand mark present?

This output drives which Layer B checks fire. Generator's declared `asset_type` is logged but never used as a gate.

### Layer A — Programmatic Checks (free, <100ms)
- **A1** Dimensions match declared platform spec
- **A2** File size and resolution within acceptable range
- **A3** File format valid and not corrupted
- **A4** Image is not blank or near-blank (pixel variance threshold)

### Layer B — Vision Model Checks

| Check | Condition to Run | Confidence Threshold |
|-------|-----------------|---------------------|
| B1 Anatomy | Humans detected | >90% = hard fail, 60–90% = flag |
| B2 Rendering Artifacts | All assets | >90% = hard fail |
| B3 Text Sanity | Text detected | >90% = hard fail |
| B4 Brand Identity Presence | Logo expected | >90% = hard fail |

### Output Format
```json
{
  "layer": "hard_failure_detection",
  "hard_fail": true,
  "failures": [
    {
      "check": "anatomy",
      "finding": "Right hand has 6 fingers",
      "instruction": "Regenerate with correct 5-finger anatomy on all hands"
    }
  ]
}
```

---

## LAYER 2 — Brand Compliance

**Question:** *Is this the right brand, executed correctly?*  
**Threshold:** ≥ 70 to proceed

### Layer A — Programmatic
**Color Palette Analysis**  
Extract dominant colors using PIL/colorgram. Compare against product brand hex values using delta-E perceptual distance.

| Delta-E | Result |
|---------|--------|
| < 10 | Acceptable match |
| 10–25 | Soft fail — flagged |
| > 25 | Hard brand fail |

### Layer B — Vision Model Checks
- **B1** Logo Presence & Correctness — right product logo, right variant, legible and unobstructed
- **B2** Typography — visible text uses correct brand font style
- **B3** Cross-Contamination — no other Symph product's visual elements present
- **B4** Visual Identity Consistency — overall visual language matches product personality

### Scoring
```
Color Compliance     40%  (programmatic)
Logo Compliance      30%  (vision model)
Typography           15%  (vision model)
Cross-contamination  15%  (vision model)
```

### Product Brand Reference Data

| Product | Primary Hex | Font | Visual Identity |
|---------|------------|------|-----------------|
| Overture | #0891b2 (Cyan) | Fraunces + Inter | Cool, composed, data-forward |
| Worklane | #9333ea (Purple) | DM Sans | Dynamic, purposeful, in motion |
| Vector | #ea580c (Orange) | Space Grotesk | Bold, forward, results-driven |
| Alignly | #059669 (Emerald) | Nunito | Warm, human, people-first |
| Clocklane | #dc2626 (Red) | IBM Plex Sans | Honest, precise, no-frills |
| Encore | #0d9488 (Teal) | Cormorant + Inter | Polished, premium, welcoming |

### Output Format
```json
{
  "layer": "brand_compliance",
  "score": 48,
  "status": "FAIL",
  "failures": [
    {
      "check": "color_palette",
      "finding": "Dominant color #9b5de5 — purple. Expected Alignly brand color #059669 — emerald.",
      "instruction": "Replace purple tones with Alignly brand emerald (#059669). No purple anywhere in this asset."
    }
  ]
}
```

---

## LAYER 3 — Aesthetic Quality

**Question:** *Would a senior art director approve this without changes?*  
**Threshold:** ≥ 80 PASS | 60–79 CONDITIONAL PASS (human review) | < 60 FAIL

### Input 1 — Trend Brief 2026 (shared, updated quarterly)

```
APPLICABLE TRENDS FOR B2B SAAS:

T1 — Authentic Imperfection
Signals: film grain, natural skin texture, candid unposed moments,
genuine expressions, emotional resonance, slight imperfection.
Anti-signals: posed stiffness, overlit studio feel, glossy AI smoothness.

T2 — Cinematic / Editorial
Signals: dramatic light/shadow contrast, strong focal hierarchy,
intentional negative space, bold compositions, high-production feel.
Anti-signals: flat even lighting, no clear subject, cluttered frame.

INVALID TRENDS FOR B2B SAAS:
- Surreal Experimentalism (Gen Z / entertainment only)
- Tactile / Organic (wellness / food only)

AI TELLS — FLAG ANY OF THESE:
- Uncanny perfect symmetry where natural asymmetry would exist
- Uniform textures (skin, fabric, surfaces) with no variation
- Physically impossible backgrounds
- Faces technically correct but emotionally "off"
- Overly vibrant colors that don't exist in the real world
- "AI glow" — subjects that seem internally lit
```

### Input 2 — Product Aesthetic Briefs

**OVERTURE**
```
Trend Lens: T2 Cinematic/Editorial (primary)
Visual Personality: Cool, composed, data-forward. Elegant boardroom
where truth is revealed without drama.
Aesthetic Signals: Strong geometric compositions, cool cyan light,
dramatic contrast, intentional negative space, data as art,
wide shots, executive environments.
Anti-Signals: warm/organic tones, cluttered layouts, casual energy,
anything rushed or imprecise.
Emotional Target: confidence, clarity, trust.
```

**WORKLANE**
```
Trend Lens: T2 Cinematic/Editorial (primary), T1 texture layer
Visual Personality: Dynamic, purposeful, things in motion. Purple
energy — decisions moving, workflows clearing.
Aesthetic Signals: Directional compositions, bold purple/shadow
contrast, process-as-motion, momentum implied through framing.
Anti-Signals: static scenes, blocked/cluttered compositions,
soft warm energy, anything implying waiting or stagnation.
Emotional Target: momentum, control, confidence.
```

**CLOCKLANE**
```
Trend Lens: T1 Authentic Imperfection (primary)
Visual Personality: Honest, grounded, no-frills. Real people in
real workplaces. Like a trustworthy accountant — nothing to hide.
Aesthetic Signals: Natural workplace lighting, candid work moments,
genuine expressions, real environments (POS, counters, desks).
Anti-Signals: glamorized workplaces, dramatic fake lighting,
over-polished surfaces, staged scenes.
Emotional Target: trust, accuracy, fairness.
```

**VECTOR**
```
Trend Lens: T2 Cinematic/Editorial (primary)
Visual Personality: High energy, directional, results-now. Orange
urgency + optimism. Never looking back.
Aesthetic Signals: Forward-facing subjects, dynamic angles, bold
color blocking, wide shots implying scale, decisive body language.
Anti-Signals: static or contemplative scenes, soft/cozy energy,
warm/domestic environments, anything that feels slow.
Emotional Target: urgency, optimism, forward motion.
```

**ALIGNLY**
```
Trend Lens: T1 Authentic Imperfection (primary)
Visual Personality: Warm, real, people-first. The most human
product in the portfolio. Groups in genuine moments.
Aesthetic Signals: Candid group moments, genuine smiles, diverse
people, natural warm-ish light, real team environments,
film grain acceptable, human imperfection welcome.
Anti-Signals: posed stock photography, cold/clinical lighting,
isolated subjects, corporate sterility.
Emotional Target: warmth, belonging, genuine connection.
```

**ENCORE**
```
Trend Lens: T2 Cinematic/Editorial (primary)
Visual Personality: Elegant, premium hospitality energy. Like
the lobby of a hotel you feel privileged to be in.
Aesthetic Signals: Wide architectural shots, dramatic premium
lighting, teal accents, minimal clutter, high-end surfaces,
anticipatory energy — everything set and waiting.
Anti-Signals: casual/informal energy, cluttered spaces,
warm/rustic textures, anything budget or utilitarian.
Emotional Target: premium, trust, exclusivity, welcome.
```

### Checks & Scoring
```
A1 — Trend Alignment         35%
  Does the asset match the product's assigned trend lens?

A2 — Intentionality          30%
  Does every element feel placed? Clear focal point?
  Visual hierarchy intact?

A3 — AI Tell Detection       20%
  0 flags = 100 | 1 flag = 70 | 2 flags = 40 | 3+ flags = 0

A4 — Emotional Target        15%
  Does the overall feeling match the product's emotional target?
```

### Output Format
```json
{
  "layer": "aesthetic_quality",
  "product": "Alignly",
  "score": 58,
  "status": "FAIL",
  "checks": {
    "trend_alignment": 55,
    "intentionality": 70,
    "ai_tell_detection": 40,
    "emotional_target": 65
  },
  "failures": [
    {
      "check": "trend_alignment",
      "finding": "Scene is posed and corporate — contradicts Authentic Imperfection standard for Alignly.",
      "instruction": "Reshoot as candid group moment. Natural light, genuine interaction, no posed smiles."
    }
  ]
}
```

---

## LAYER 4 — Content Relevance

**Question:** *Does this asset actually say what it was supposed to say?*  
**Threshold:** ≥ 70 to proceed  
**Requires:** Asset Packet (brief must be present)

The Reviewer compares the brief to the image — not the other way around. The brief is ground truth. The Generator cannot rewrite it mid-loop.

### Checks & Scoring
```
C1 — Brief Fidelity          40%
  Correct subject, setting, key visual elements?
  Nothing from the brief conspicuously missing?

C2 — Message Clarity         30%
  Primary message clear in under 3 seconds?
  Visual hierarchy correct? Text legible?

C3 — Platform Energy         20%
  LinkedIn   → professional, measured, credibility-first
  Instagram  → visually arresting, immediate hook, emotional
  TikTok/Reels → dynamic, vertical, scroll-stop in 0–3s
  Twitter/X  → punchy, direct, minimal cognitive load

C4 — Audience Alignment      10%
  Speaks to the right person?
  B2B decision makers: managers, ops leads, C-suite
```

### Output Format
```json
{
  "layer": "content_relevance",
  "product": "Vector",
  "score": 52,
  "status": "FAIL",
  "brief_received": {
    "subject": "team sprint planning session",
    "setting": "modern open office",
    "key_message": "Move fast. Ship faster.",
    "platform": "LinkedIn",
    "audience": "Engineering managers"
  },
  "failures": [
    {
      "check": "brief_fidelity",
      "finding": "Image shows one person working alone. Brief specified team sprint — group dynamic missing.",
      "instruction": "Regenerate with 3–5 people around a shared screen or whiteboard. Collaboration must be visible."
    }
  ]
}
```

---

## LAYER 5 — Platform Fit

**Question:** *Is this technically ready for where it's going?*  
**Type:** Checklist — hard fails vs. soft flags  
**Auto-fix where possible before escalating back to Generator**

### Platform Dimension Specs
```
Instagram Feed:        1080×1080 (1:1) or 1080×1350 (4:5)
Instagram Stories/Reels: 1080×1920 (9:16)
LinkedIn:              1200×627 (16:9) or 1080×1080 (1:1)
Twitter/X:             1200×675 (16:9) or 1080×1080 (1:1)
TikTok:                1080×1920 (9:16)
```

### Safe Zone Reference
```
Instagram Stories/Reels:
  Top 250px    → system UI
  Bottom 250px → CTA bar, handle

TikTok:
  Right 150px  → action bar
  Bottom 300px → caption + handle

LinkedIn/Feed: 100px inset from all edges for critical content
```

### Checks

| Check | Method | Failure Path |
|-------|--------|-------------|
| P1 Dimensions | Programmatic | Auto-crop/resize → check safe zones → pass or escalate |
| P2 Safe Zones | Vision model (light) | Back to Generator — layout must change |
| P3 Text Density | Programmatic (pixel) | Flag if >20% (Meta ad limit) — conditional pass |
| P4 Display Weight | Vision model (thumbnail test) | Back to Generator if primary elements dissolve at 150×150 |
| P5 File Format/Size | Programmatic | Auto-convert/compress → re-check → pass |

### Failure Routing Decision Tree
```
P1 fail → auto-fix possible? → fix → re-check
                             → no → back to Generator
P2 fail → always back to Generator (layout change required)
P3 flag → conditional pass, logged
P4 fail → back to Generator ("increase visual weight of [element]")
P5 fail → auto-fix → re-check → pass
```

### Output Format
```json
{
  "layer": "platform_fit",
  "platform": "Instagram Stories",
  "status": "FAIL",
  "auto_fix_attempted": true,
  "checks": {
    "dimensions": "PASS",
    "safe_zones": "FAIL",
    "text_density": "PASS",
    "display_weight": "PASS",
    "file_format": "PASS"
  },
  "failures": [
    {
      "check": "safe_zones",
      "finding": "Product logo at bottom 180px — falls inside action bar zone.",
      "fix_possible": false,
      "instruction": "Move logo to upper-left quadrant, minimum 300px from bottom edge."
    }
  ]
}
```

---

## Loop Controller

Manages iteration count, routes critique, and triggers human escalation.

```
MAX_ITERATIONS = 5

Each loop:
  1. Generator receives full critique from failed layer
  2. Generator regenerates and increments generation_attempt
  3. Pipeline restarts from Layer 1
  4. If generation_attempt > MAX_ITERATIONS → ESCALATE

ESCALATE means:
  - Stop generation loop
  - Flag asset for human review
  - Deliver best attempt so far with full audit trail
  - Log escalation reason to qa-reports.json
```

### Final Score Calculation (on full pass)
```
Layer 2 (Brand)       30%
Layer 3 (Aesthetic)   35%
Layer 4 (Relevance)   25%
Layer 5 (Platform)    10%

Overall pass threshold: ≥ 80
```

---

## QA Report Schema

Every asset run writes to `qa-reports.json`:

```json
{
  "asset_id": "uuid",
  "product": "Alignly",
  "platform": "Instagram Stories",
  "generation_attempts": 3,
  "final_status": "PASS",
  "final_score": 84,
  "layer_scores": {
    "layer_2": 92,
    "layer_3": 81,
    "layer_4": 78,
    "layer_5": "PASS"
  },
  "escalated": false,
  "delivered_at": "2026-02-23T14:00:00Z",
  "audit_trail": [
    {
      "attempt": 1,
      "failed_at": "layer_3",
      "score": 51,
      "critique_summary": "AI tells detected, wrong trend lens for product"
    },
    {
      "attempt": 2,
      "failed_at": "layer_2",
      "score": 62,
      "critique_summary": "Color drift after style correction"
    },
    {
      "attempt": 3,
      "passed_all": true
    }
  ]
}
```

---

## Maintenance

| Task | Frequency | Owner |
|------|-----------|-------|
| Trend Brief refresh | Quarterly | ARIA + design lead |
| Product Aesthetic Brief update | On rebrand | Design lead |
| Platform specs check | Monthly | ARIA |
| Scoring weight calibration | After every 50 assets | ARIA + loewe |

---

## Implementation Stack (Proposed)

| Component | Tool |
|-----------|------|
| Layer A programmatic checks | Python + PIL/Pillow |
| Color analysis | colorgram or Pillow color extraction |
| Vision model calls | Gemini Vision or GPT-4V |
| OCR for text sanity | pytesseract or Google Vision API |
| Pipeline orchestration | Python orchestrator script |
| QA logging | Append to qa-reports.json |

---

*Spec v1.0 — Ready for implementation planning*
