---
id: "6.3"
title: "Guards"
dept: ai-and-models
status: draft
owner: Param
branded: false
last_verified: 2026-10-26
sources:
  - "brew origin/main b91e364: claims.js:1-232, image-guard.js:1-142, draft-quality.js:1-109, text-check.js:1-55, fact-gate.js:1-12, research.js:57, proof-logic.js:128"
  - "brew origin/main: server.js:212-236, remix.js:622-650, moves-engine.js:540-575, jam2/creative.js:95-135, jam2/studio.js:88 and 133-142, brand-book-read.js:205, ai.js:9-11"
  - "brew origin/main test/: claims, claim-kinds, claim-rules, round2-claims, writer-slips, image-guard, draft-quality, text-check, fact-truth, honest-copy, proof-logic, make-claim, brand-book-guards, qv3-guards"
  - "memory brew-draft-quality, brew-brand-book-guards, brew-proof-plain-make, brew-sloosh-finals, brew-viral-remakes, brew-jam-v2, brew-setup-v2, brew-qa-audit-2026-10-20"
---

# Guards

## Answer

The checks that sit between a model's output and a person: what each one catches, what it does when it fires, and the rule that every guard works for every brand and heals saved work, so nothing a model invents reaches a shopper unchecked.

## Today

### Words: claims

`claimFlags(text, source)` flags five kinds of claim the brand's own words do not carry [src: brew/claims.js:64-82].

| Kind | Example it catches | Passes when | Source |
|---|---|---|---|
| code | "Use code PURE25" | The code is on the store | [src: brew/claims.js:24-25] |
| guarantee | "money back", "risk free" | The store says it | [src: brew/claims.js:26] |
| timed | "visible results in 14 days", "overnight results" | The store says the same time | [src: brew/claims.js:28] |
| absolute | "clinically proven", "dermat-approved", "100% natural", "cures" | Health words need the study, test or certificate beside them in the store's words, or a Brand Book approved claim; other absolutes need the store's own words | [src: brew/claims.js:32] [src: brew/claims.js:74-78] |
| efficacy | "up to 60% less hair fall", "reduce hair fall by 7.4X" | The store names where the number was measured, or the claim is approved | [src: brew/claims.js:36-37] |

- "Dermat-approved" passed once on Arata and is now caught in every spelling [src: brew/claims.js:30-31].
- An approved claim counts only inside the Brand Book's approved list, never anywhere in the brand's words [src: brew/claims.js:50-52].
- Every writer prompt carries `CLAIMS_RULE` [src: brew/claims.js:88].

What happens when a claim fires depends on the surface:

| Surface | Action | Source |
|---|---|---|
| A Play | Sentence kept, marked "Proposed, team decides"; a claim in a title or cover number goes to To confirm | [src: brew/claims.js:102-137] |
| A draft made with nobody watching | Every flagged sentence dropped; a flagged headline never set on the picture | [src: brew/claims.js:143-153] |
| A feed card that no person rewrites | Sentences with codes or guarantees dropped | [src: brew/claims.js:93-97] |
| Anything a shopper, team or partner may copy | `checkCopy` drops flagged sentences, never throws | [src: brew/claims.js:215-232] |
| A film's spoken line | Claim taken out before the model hears it | [src: brew/jam2/studio.js:133] |
| A still's words | A claim, or a price that is not this product's own, is taken out | [src: brew/jam2/studio.js:134-142] |

### Words: banned words, copy and slips

- `bannedHits` finds category words ads cannot use, but never inside quotes, a denial, an avoid list, or a word the brand itself uses [src: brew/claims.js:110-118]. The banned list is config plus the Brand Book never-say list [src: memory brew-brand-book].
- `copyFlags` flags shouting caps, forced slang, nonsense time phrases, repeated words and literal "\n" [src: brew/claims.js:166-195]. Every writer carries `COPY_RULE` [src: brew/claims.js:196].
- `writerSlips` adds the "isn't A; it's B" turn, paise on a price the store shows whole, and for WhatsApp or SMS: dash lists, label lines, over 700 characters [src: brew/claims.js:203-213].
- **Mend:** a jam package with slips is rewritten once on exactly those slips before anyone sees it, so "Needs a fix" never lands on a fresh draft [src: brew/remix.js:642-650]. Added 26 Oct after an Arata WhatsApp broadcast [src: brew/claims.js:199-202].
- Every structured reply gets real line breaks, and ₹ written as ‹ is fixed [src: brew/ai.js:9-11].

### Numbers and proof

- **Fact gate:** every money amount and percentage on a card must be on the fact sheet; strict mode also gates multipliers and large counts [src: brew/fact-gate.js:1-12].
- **Honest:** a story quotes only numbers in its data, small counts up to 10 aside [src: brew/research.js:57].
- **Play check:** each Play is read by a second model against the lines it cites, and only flagged sentences are fixed; an unbacked number becomes a labelled target [src: brew/moves-engine.js:553] [src: brew/moves-engine.js:568].
- **Proof:** the proof sheet must prove the claim it sits under; prices, plan rows and Plays are never proof [src: brew/proof-logic.js:128] [src: memory brew-proof-plain-make].
- **Brand Book verify:** a line without a citation or a verbatim quote is dropped [src: brew/brand-book-read.js:205]. The Brand Book has its own audit and guard test before every deploy [src: memory brew-brand-book-guards].

### Pictures: the image guard

One wrapper around the image model gives every caller the same checks [src: brew/image-guard.js:1-24].

| Step | What it does | Source |
|---|---|---|
| Reference | The product the words name, matched to the catalog; its plainest photo; never a logo | [src: brew/image-guard.js:74-90] |
| Keep | The prompt says to keep the product exactly as photographed | [src: brew/image-guard.js:29] |
| Product check | SAME keeps it; TEXT remakes once on the other model, turned and smaller; DIFFERENT remakes stricter, then the real photo stands in; NOREF tries the next catalog photo | [src: brew/image-guard.js:110-140] [src: brew/server.js:212-230] |
| Look judge | A free pixel check, then a vision judge: GOOD, COLLAGE, CROPPED, OFFTOPIC, EXPERT | [src: brew/image-guard.js:57-59] [src: brew/draft-quality.js:91-98] |
| Redo or hold back | A failure is made once more with the reason; a second failure is held back and never shown | [src: brew/image-guard.js:60-72] |
| Retry | Up to 3 tries with backoff; a blocked or refused prompt is not retried | [src: brew/image-guard.js:43-50] |

- The pixel check flags two flat grounds of different colours at the frame, or a blank band; it is strict on purpose, FLAT 2.5 and 10% of the frame [src: brew/draft-quality.js:37] [src: brew/draft-quality.js:56-68] [src: memory brew-draft-quality].
- EXPERT fails any person shown as a doctor or scientist, a fake endorsement; saved drafts were judged again at `LOOKS_V` 2 [src: brew/draft-quality.js:15] [src: brew/draft-quality.js:97].
- When in doubt the judge says GOOD; split screens pass and page mocks are never judged [src: brew/draft-quality.js:93] [src: memory brew-draft-quality].
- See-through packshots are flattened on white before the model sees them [src: memory brew-draft-quality].
- A cut-out with no real matte or a jagged edge is never placed [src: brew/draft-quality.js:73-88].
- Of 54 pictures the old check threw away on 16 Oct, 47 showed the right product, so blurred small print now counts as SAME [src: brew/server.js:218].

### Studio and finals

- **Critic:** each Studio shot is judged against the product photo; a check that did not run never buys a second picture [src: brew/jam2/creative.js:99-109].
- **Made check:** every word a designed piece drew is read back; an invented size, number, claim or fake review fails it. Higgsfield once printed "10ml" on a 30 ml bottle and set a tagline as a 5-star review [src: brew/jam2/creative.js:111-131].
- A take that fails its checks is retried once, never more [src: brew/jam2/studio.js:1-5].
- A testimonial style is blocked when the Brand Book says no testimonials [src: brew/jam2/studio.js:88].
- **Video spelling:** after a video final lands, two frames per worded beat are read and compared with the words asked for; nothing is remade by itself because a remake costs credits [src: brew/text-check.js:1-5] [src: brew/text-check.js:50-55]. Added after Arata's reel read "concrate" [src: memory brew-viral-remakes].

### Tests that hold the guards

Guard tests run on every deploy with `AI_MOCK=1`, and a failing suite stops the deploy [src: brew/deploy.sh:12-16]. Files: claims, claim-kinds, claim-rules, round2-claims, writer-slips, make-claim, fact-truth, honest-copy, proof-logic, image-guard, draft-quality, text-check, brand-book-guards, qv3-guards [src: brew/test/].

## Tomorrow

| Item | Version | Tag |
|---|---|---|
| Every guard brand-agnostic, healing saved work on read | v1 | Stays |
| A labelled claim corpus that measures precision and recall of `claimFlags` | v1 | New, see Evals |
| Guard verdicts logged per brand and per day, so a rising hold-back rate shows | v1 | New |
| Video spelling check that offers one remake with the price shown | v2 | Changes |
| A send gate: nothing posts or schedules without guards passing and a person's yes | v2 | New |
| Ad policy checks per platform before an ad runs | v4 | New |
| Category rule packs, such as ASCI, FSSAI, FTC, ASA, kept as Brand Book suggestions until the team keeps them | v1 | Stays [src: memory brew-brand-book] |

## How we do it

1. A new surface that a shopper, team or partner can copy calls `checkCopy` or `checkCopyIn` with `packSource(pack, card)` [src: brew/claims.js:57] [src: brew/claims.js:215-232].
2. A new picture caller goes through the image guard, never the raw model.
3. A new incident class gets a guard in code, a test, and a heal for saved data, the same day.
4. Run the guards locally:
   ```bash
   cd /Users/param/Documents/ChatGPT/brew
   AI_MOCK=1 node --test test/claims.test.js test/writer-slips.test.js test/image-guard.test.js test/draft-quality.test.js test/text-check.test.js
   ```
5. Turn the look judge off only to diagnose: `LOOKS_CHECK=0`. `IMAGE_CHECK=0` turns off both picture checks [src: brew/server.js:232].
6. Before a Brand Book deploy: `node tools/audit-brand-book.mjs DIR` and the guards test [src: memory brew-brand-book-guards].

## Numbers

| Metric | Definition | Where measured | Status |
|---|---|---|---|
| Hold-back rate | Pictures held back after two look failures, over pictures made | `guard.held` on each picture [src: brew/image-guard.js:70-71] | Proposed, not counted today |
| Wrong product shipped | Pictures shown whose product is not the catalog product | spot check | Proposed, target 0 |
| Mend rate | Jam packages rewritten on slips, over packages made | remix.js mend | Proposed |
| Claim flags per 100 drafts | Flags removed by Clean | `cleanDraftClaims` return | Proposed |
| Video spelling pass | Finals whose on-screen words match | text-check result | Proposed |

## Open

1. **Count the guards.** Nothing records how often each guard fires. Proposal: one daily line per brand in the ops page with flags, mends, redos and holds.
2. **Judge model.** The picture checks ask for Haiku and run on Flash today. Proposal: keep Flash until the eval set shows judge agreement with a person below 90%, then move the judge to Claude.
3. **Video spelling remake.** Proposal: keep it manual in v1, and in v2 offer one priced remake.
