Answer
Every place Brew asks a model for words or a verdict: its tag, file and line on origin/main, what it feeds, the tier it asks for and what runs today, and the guard that checks its output before anyone sees it.
Today
How to read the tiers
- Opus asks for
claude-opus-5-5and runs onGEMINI_DEEP_MODEL,gemini-3.5-flashtoday brew/ai.js:7 brew/gemini-client.js:14 brew/tools/prod-env.sh:9. - Plays ask for
MOVE_MODEL(): Opus on Claude,gemini-3.1-pro-previewtoday brew/moves-engine.js:17. - Sonnet asks for
claude-sonnet-5-5and runs ongemini-3.5-flashtoday brew/ai.js:7. - Jam is
claudeToolorclaudeJSONin server.js:claude-sonnet-5-5, effort low, thinking off, structured output, Flash today brew/server.js:116 brew/server.js:139-171. - Haiku is the picture check,
claude-haiku-5-5, Flash today brew/server.js:223. - Calls through ai.js are metered in dollars by tag brew/ai.js:51. Jam calls are counted only as daily
textunits brew/budget.js:12-15.
The guards named below
| Guard | What it checks | Where |
|---|---|---|
| Claims | Invented codes, guarantees, timed results, health absolutes, measured results | brew/claims.js:64-82 |
| Mark | A claim in a Play is kept but marked "Proposed, team decides" or moved to To confirm | brew/claims.js:102-137 |
| Clean | A draft made with nobody watching loses every flagged sentence | brew/claims.js:143-153 |
| Check copy | One entry point for every copyable surface; drops flagged sentences | brew/claims.js:219-232 |
| Slips and mend | Claims, the "isn't A; it's B" turn, paise on prices, WhatsApp shape; rewritten once | brew/claims.js:203-213 brew/remix.js:644 |
| Copy flags | Shouting caps, slang, repeated words, literal line breaks | brew/claims.js:166-195 |
| Fact gate | Every money amount and percentage must be on the fact sheet | brew/fact-gate.js:1-12 |
| Honest | Every number in a story must be in its source data | brew/research.js:57 |
| Proof | The proof shown must prove the claim | brew/proof-logic.js:128 |
| Play check | A second model reads each Play against its evidence; flagged lines are fixed | brew/moves-engine.js:553 brew/moves-engine.js:568 |
| Book verify | Brand Book lines without a citation or a verbatim quote are dropped | brew/brand-book-read.js:205 |
| Picture guards | Product match, look judge, made-piece read-back, video spelling | see the Guards document |
| Schema | Structured output with every field required; parse failure throws | brew/ai.js:18-27 brew/server.js:166-171 |
Build: the brand read
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
reader-line |
brew/reader/stages/answers.js:32 | The one-line description of the brand | Sonnet, Flash | Length and word rules in code, never over a line the brand typed brew/reader/stages/answers.js:18 |
reader-category |
brew/reader/stages/answers.js:52 | Category, subcategory, search terms | Sonnet, Flash | Kept from the first read after that |
reader-questions |
brew/reader/stages/answers.js:85 | 8 shopper questions for the AI answers check | Sonnet, Flash | Template questions stand in when it fails |
reader-answer |
brew/reader/stages/answers.js:106 | Claude's answer to a shopper question, with web search | Sonnet, only when provider is anthropic | Skipped under Gemini brew/reader/stages/answers.js:110 |
reader-company |
brew/reader/stages/company.js:24 | Company facts, web search 6 | Sonnet, Flash | Cited lines go to the ledger |
reader-named |
brew/reader/stages/named.js:32 | Which brands AI answers name | Sonnet, Flash | Timeout; error kept, never zeros |
reader-about |
brew/reader/stages/open.js:218 | About text from the site | Sonnet, Flash | none beyond schema |
reader-rivals, reader-rivals-retry |
brew/reader/stages/ads.js:81-82 | Rivals with a cited web search | Sonnet, Flash, search 4 | Rivals must then be read for ads; errors are errors memory brew-external-data-skill |
reader-rivals-alt, reader-rivals-known |
brew/reader/stages/ads.js:113 and 120 | More rivals when fewer than 3 | Sonnet, Flash | same |
ai-questions-seeds, ai-questions-pick |
brew/ai-questions.js:81 and 108 | Questions sourced from search data and threads | Sonnet, Flash | The model only picks; the reason is built in code memory brew-proof-plain-make |
brandbook-read |
brew/brand-book-read.js:282 | Brand Book story, voice, words, claims, look | Sonnet low, Flash | Book verify |
untagged claude() calls |
brew/research.js:167-445 | Stories: rival ad notes, interests, trends, how-to, news | Jam params, Flash | Honest numbers |
video_text_check, video reads |
brew/video-read.js:97-125 | What a video shows: format, beats | gemini-3.5-flash direct, Sonnet fallback |
Schema |
Build: brief, Plays, cards
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
brief |
brew/brief.js:108 | The brand brief every Play reads | Opus high, Flash | Fact gate |
move00 |
brew/moves-engine.js:652 | The index Play | Plays tier, Pro | Claims rule in the prompt, Mark |
moveNN |
brew/moves-engine.js:473 | Each Play, system and brand block cached 1 hour | Plays tier, Pro, effort medium, up to 48,000 tokens | Claims rule, Play check, Mark, fact gate brew/moves-engine.js:471-473 |
moveNN-retry, moveNN-whole |
brew/moves-engine.js:476-490 | A Play that failed or came back cut | Plays tier, effort low | same |
verifyNN |
brew/moves-engine.js:553 | Checks each Play against the lines it cites | Sonnet low, Flash | is itself the guard |
fixNN |
brew/moves-engine.js:568 | Rewrites only flagged lines; unbacked numbers become labelled targets | Sonnet medium, Flash | Play check again |
moves-<family> |
brew/moves-cadence.js:387 | Weekly cadence Plays | Sonnet medium, Flash | Honest, fact gate |
move-value |
brew/value.js:62 | Grades the value of each Play | Sonnet, Flash | Schema |
cards |
brew/cards-gen.js:273 | Feed cards written from Plays and reads | Sonnet, Flash | Fact gate strict, Claims, Check copy |
cards-claims |
brew/cards-gen.js:326 | Rewrites a card whose claims failed | Sonnet, Flash | Claims |
cards-read |
brew/cards-gen.js:345 | Cards from the read's findings | Sonnet, Flash | Fact gate, Check copy |
plain_cards |
brew/plain.js:164 | Plain-words rewrite of every card, 12 at a time | Jam, Flash | Numbers checked in code, Claims memory brew-proof-plain-make |
notes |
brew/notes.js:54 | Team notes | Sonnet, Flash | Schema |
statics |
brew/statics.js:103 | Static ad words | Sonnet, Flash | Claims rule, Check copy, fact gate |
ideas:slate |
brew/ideas.js:382 | Which ideas to write | Opus medium, Flash | Honest |
ideas:write |
brew/ideas.js:400 | The ideas themselves | Opus high, Flash | Claims, Check copy, fact gate |
ideas:check |
brew/ideas.js:524 | A second read of the ideas | Sonnet, Flash | is itself the guard |
refresh-triage |
brew/refresh.js:122 | Which Plays a site change affects | Sonnet, Flash | Feeds the capped rewrite pot |
calendar-<slug>, calendar-confirm |
brew/calendar.js:99 and 144 | Which dates matter, and confirming one from news | Sonnet, Flash | A date needs a source |
pulse-questions-<slug> |
brew/market-pulse.js:65 | Weekly market questions | Sonnet, Flash | Schema |
listen-indirect-, listen-config-, listen-tag-<slug> |
brew/listen-watch.js:181, 225, 620 | What to listen for, and tagging what was heard | Sonnet, Flash | Community gate downstream |
measure-family, propose |
brew/measure-families.js:108 and 149 | Which measurement family a card belongs to | Jam, Flash | Enum of known families |
facts-link |
brew/facts-desk.js:214 | Links a fact to its source | Sonnet, Flash | Numbers |
Learning and memory
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
learn-extract, learn-plan |
brew/brand-learnings.js:378 and 386 | Turns a team upload into learnings and a rewrite plan | Sonnet medium and low, Flash | Learn cap $30 |
memory-extract, memory-decide, memory-learn, memory-dream |
brew/brand-memory.js:158, 164, 407, 445 | Brand memory | Sonnet, Flash | Schema |
drop-read |
brew/drop-read.js:83 and 88 | Reads anything dropped into Brew | Sonnet low, Flash | Schema |
brandbook-ask, brandbook-import |
brew/brand-book-routes.js:128 and 227 | Change the Brand Book in words | Sonnet low, Flash | Proposal the team confirms |
pref-sides |
brew/feed-service.js:1980 | Preferences from a dropped text | Jam, Flash | Schema |
learn |
brew/feed-service.js:1671 | A lesson from a step the person took | Jam, Flash | Schema |
| map wants | brew/feed-service.js:1743 | Maps what a founder said to card types | Jam JSON, Flash | none beyond parse |
Feed, jam and chat
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
| scheduled idea card | brew/feed-service.js:949 | One new ad idea card on a schedule | Jam JSON, Flash | Check copy downstream |
| more like this | brew/feed-service.js:1223 | A new card in the direction of a hearted one | Jam JSON, Flash | Fact gate, Claims |
| route | brew/feed-service.js:1239 | Sends a message to AI or to a person on our team | Jam JSON, Flash | Enum |
versions |
brew/feed-service.js:1252 | One new version of a card | Jam, Flash | Fact gate, Claims |
| sort message | brew/feed-service.js:1574 | Sorts a chat message: chat, question, change, make, yes, no | Jam, Flash | Enum |
colleague |
brew/feed-service.js:1606 | A reply in Slack as a role | Jam, Flash | Check copy |
jam_answer |
brew/jam-answer.js:79 | Grounded answer to a question, from evidence | Jam, Flash | Claims; says "I don't know" when unknown |
canvas |
brew/feed-service.js:1693 | Picks the blocks that show the work | Jam, Flash | Enum of blocks |
card_page |
brew/feed-service.js:2338 and 2353 | The card's own page | Jam, Flash | Fact gate, every number from the fact brief or the measure |
draft |
brew/drafts.js:81 | A draft from a card | Jam, Flash | Claims rule, Copy rule, Clean |
draft-bg |
brew/drafts-bg.js:224 | First drafts made with nobody watching | Sonnet, Flash | Clean, fact gate |
brief_plan |
brew/jam-brief.js:199 | The plan pulled out of a jam brief | Jam, Flash | "Copy values exactly; never invent" in the prompt |
jam_doc |
brew/jam-brief.js:214 | Rewrites the jam brief as asked | Jam, Flash | Check copy |
| jam question | brew/jam-brief.js:294 | Answers a question in the brief | Jam, Flash | Grounded answer |
team_brief, team_brief_edit |
brew/team-brief.js:90 and 175 | The brief sent to an agency or team | Jam, Flash | Check copy |
remix_options |
brew/remix.js:633 | The package a jam makes | Jam, Flash | Claims rule, Copy rule |
remix_mend |
brew/remix.js:644 | Rewrites a package once on its slips | Jam, Flash | Slips and mend |
| jam chat answer | brew/remix.js:1051 | Answers in the jam room | Jam, Flash | Grounded answer, Proof |
studio_iterate |
brew/remix.js:1072 | An edit to the package | Jam, Flash | Check copy |
jam_answer suggestion |
brew/remix.js:1146 | A suggested answer to an open question, for the team to confirm | Jam, Flash | Marked as a suggestion |
v2_words |
brew/remix.js:1495 | Rewrites only the words | Jam, Flash | Copy rule |
impact |
brew/remix.js:1963 | Expected impact of a change | Jam, Flash | Inputs built in code |
remake |
brew/remix.js:1999 | Our version of a rival ad or viral video | Jam, Flash | The rival's words are never reused |
| named stage | brew/server.js:444 | Brands named in saved AI answers | Sonnet, Flash | Schema |
Studio
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
jam2_direct |
brew/jam2/creative.js:78 | Art direction: format, moment, calm zone | Jam, Flash | Brand Book look and people rules |
jam2_critic |
brew/jam2/creative.js:105 | Vision check of each shot against the product | Sonnet low, Flash | is itself the guard |
jam2_made_check |
brew/jam2/creative.js:126 | Reads back every word a designed piece drew | Sonnet low, Flash | is itself the guard, plus Claims |
jam2_write |
brew/jam2/make.js:94 | Headline, caption, script for a board | Jam, Flash | Claims, banned words |
jam2_headline |
brew/jam2/make.js:98 | A headline when the writer left it empty | Jam, Flash | 7 words at most |
jam2_places |
brew/jam2/make.js:267 | Empty settings for video shots | Jam, Flash | No product drawn by AI |
jam2_line |
brew/jam2/make.js:484 | Rewrites one line | Jam, Flash | "Same facts only" in the prompt |
product_profile |
brew/jam2/profiles.js:40 | What a product is, label, size | Sonnet low, Flash | Schema |
studio_ask |
brew/jam2/routes.js:202 | Turns a request into set-up changes | Jam, Flash | Change only what was asked |
Pictures and video checks
| Tag | Where | Feeds | Tier | Guard |
|---|---|---|---|---|
| product check | brew/server.js:220-230 | SAME, TEXT, DIFFERENT or NOREF for every generated picture | Haiku, Flash | is itself the guard |
| look judge | brew/server.js:231-236 | GOOD, COLLAGE, CROPPED, OFFTOPIC or EXPERT | Haiku, Flash, LOOKS_CHECK=0 turns it off |
is itself the guard |
video_text_check |
brew/text-check.js:34-50 | On-screen words of a video final read back | Jam, Flash | is itself the guard |
| live Claude ask | brew/live-watch.js:159-170 | Weekly AI answers check, Claude's turn | direct client, only on anthropic | Skipped under Gemini |
Tomorrow
| Item | Version | Tag |
|---|---|---|
| Every tag listed in one data file with tier, effort, max tokens and guard; the code reads it | v2 | New |
| A test that fails when a call site has no tag or no listed guard | v1 | New |
| Jam calls metered in dollars like ai.js calls | v1 | Changes |
| Untagged research.js and live-watch.js calls get tags | v1 | Changes |
| Prompts kept in prompts/ files where long, so a prompt change shows in review | v2 | Changes |
| Writers that post or schedule for the brand get the same guards plus a send gate | v2 | New |
How we do it
- Rebuild this list from origin/main:
cd /Users/param/Documents/ChatGPT/brew git grep -n -E 'claudeTool\(|ai\.call\(|claudeJSON\(' origin/main -- '*.js' ':!test/*' ':!public/*' git grep -n -E "tag: *['\`]" origin/main -- '*.js' ':!test/*' ':!public/*' | grep -v treg - A new prompt gets a tag of the form
<what>or<what>-<slug>, a tier, and a guard from the table above before it ships. - Every writer prompt that a shopper may read carries
CLAIMS_RULEandCOPY_RULEbrew/claims.js:88 brew/claims.js:196. - Every output a shopper may copy goes through
checkCopyorcheckCopyInbrew/claims.js:215-232. - Update this document in the same change.
Numbers
| Metric | Definition | Where measured | Status |
|---|---|---|---|
| Call sites | Count of AI call sites on origin/main | the grep above; about 98 on 26 Oct | Live |
| Unguarded sites | Sites that feed a shopper-facing surface with no guard | this table | Proposed, target 0 |
| Spend by tag | Dollars per tag per day | ai.js meter.byTag brew/ai.js:51 |
Live, not reported |
Open
- Should the registry become code? Proposal: yes, a
data/prompts.jsonread by ai.js and server.js, in v2, with a test that every call site is listed. - Which tags need a stronger tier first? Proposal: brief and
ideas:writemove to Pro with the Plays, because they asked for Opus and every Play reads the brief.