{
 "id": "6.2",
 "title": "Prompts registry",
 "department": "AI and models",
 "department_slug": "ai-and-models",
 "direction": null,
 "branded": false,
 "status": "draft",
 "owner": "Param",
 "last_verified": "Mon Oct 26",
 "holds": "Every prompt, where it lives, what it feeds, its guard",
 "urls": {
  "html": "https://handbook.joinsquareup.com/ai-and-models/prompts-registry",
  "markdown": "https://handbook.joinsquareup.com/ai-and-models/prompts-registry.md",
  "json": "https://handbook.joinsquareup.com/ai-and-models/prompts-registry.json"
 },
 "other_directions": [],
 "tldr": {
  "headline": "Every Brew model call, with its guard, on one list",
  "points": [
   {
    "icon": "book",
    "text": "Each AI call has a tag, a file and line, a tier and what runs today."
   },
   {
    "icon": "lock",
    "text": "A guard checks the output before anyone sees it: claims, fact gate, check copy."
   },
   {
    "icon": "gear",
    "text": "Opus, Plays, Sonnet, Jam and Haiku are tiers; today Flash answers all except Plays."
   },
   {
    "icon": "warn",
    "text": "Jam calls have no dollar meter, and a few research calls have no tag."
   },
   {
    "icon": "rocket",
    "text": "In v2 the list becomes a data file the code reads, so it cannot drift."
   }
  ],
  "stat": {
   "value": "98",
   "label": "AI call sites, about"
  },
  "decide": "Should the registry become code in v2, and should the brief and ideas move to Pro?",
  "mood": "building"
 },
 "sources": [
  "brew origin/main b91e364: git grep -n -E 'claudeTool\\(|ai\\.call\\(|claudeJSON\\(' and git grep -n \"tag: '\" over every .js outside test/ and public/, 74 plus 24 call sites, each read in place",
  "brew origin/main: server.js:116-171 and 220-236, ai.js:7-95, gemini-client.js:14, research.js:167-445, live-watch.js:149-170, text-check.js:34-50, jam-answer.js:73-79, plain.js:164, fact-gate.js:1-12, claims.js, proof-logic.js:128",
  "memory brew-pro-switch-and-flush, brew-proof-plain-make, brew-draft-quality"
 ],
 "open_questions": [
  "**Should the registry become code?** Proposal: yes, a `data/prompts.json` read 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:write` move to Pro with the Plays, because they asked for Opus and every Play reads the brief."
 ],
 "parts": {
  "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\n\n- **Opus** asks for `claude-opus-5-5` and runs on `GEMINI_DEEP_MODEL`, `gemini-3.5-flash` today [src: brew/ai.js:7] [src: brew/gemini-client.js:14] [src: brew/tools/prod-env.sh:9].\n- **Plays** ask for `MOVE_MODEL()`: Opus on Claude, `gemini-3.1-pro-preview` today [src: brew/moves-engine.js:17].\n- **Sonnet** asks for `claude-sonnet-5-5` and runs on `gemini-3.5-flash` today [src: brew/ai.js:7].\n- **Jam** is `claudeTool` or `claudeJSON` in server.js: `claude-sonnet-5-5`, effort low, thinking off, structured output, Flash today [src: brew/server.js:116] [src: brew/server.js:139-171].\n- **Haiku** is the picture check, `claude-haiku-5-5`, Flash today [src: brew/server.js:223].\n- Calls through ai.js are metered in dollars by tag [src: brew/ai.js:51]. Jam calls are counted only as daily `text` units [src: brew/budget.js:12-15].\n\n### The guards named below\n\n| Guard | What it checks | Where |\n|---|---|---|\n| Claims | Invented codes, guarantees, timed results, health absolutes, measured results | [src: brew/claims.js:64-82] |\n| Mark | A claim in a Play is kept but marked \"Proposed, team decides\" or moved to To confirm | [src: brew/claims.js:102-137] |\n| Clean | A draft made with nobody watching loses every flagged sentence | [src: brew/claims.js:143-153] |\n| Check copy | One entry point for every copyable surface; drops flagged sentences | [src: brew/claims.js:219-232] |\n| Slips and mend | Claims, the \"isn't A; it's B\" turn, paise on prices, WhatsApp shape; rewritten once | [src: brew/claims.js:203-213] [src: brew/remix.js:644] |\n| Copy flags | Shouting caps, slang, repeated words, literal line breaks | [src: brew/claims.js:166-195] |\n| Fact gate | Every money amount and percentage must be on the fact sheet | [src: brew/fact-gate.js:1-12] |\n| Honest | Every number in a story must be in its source data | [src: brew/research.js:57] |\n| Proof | The proof shown must prove the claim | [src: brew/proof-logic.js:128] |\n| Play check | A second model reads each Play against its evidence; flagged lines are fixed | [src: brew/moves-engine.js:553] [src: brew/moves-engine.js:568] |\n| Book verify | Brand Book lines without a citation or a verbatim quote are dropped | [src: brew/brand-book-read.js:205] |\n| Picture guards | Product match, look judge, made-piece read-back, video spelling | see the Guards document |\n| Schema | Structured output with every field required; parse failure throws | [src: brew/ai.js:18-27] [src: brew/server.js:166-171] |\n\n### Build: the brand read\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| `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 [src: brew/reader/stages/answers.js:18] |\n| `reader-category` | brew/reader/stages/answers.js:52 | Category, subcategory, search terms | Sonnet, Flash | Kept from the first read after that |\n| `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 |\n| `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 [src: brew/reader/stages/answers.js:110] |\n| `reader-company` | brew/reader/stages/company.js:24 | Company facts, web search 6 | Sonnet, Flash | Cited lines go to the ledger |\n| `reader-named` | brew/reader/stages/named.js:32 | Which brands AI answers name | Sonnet, Flash | Timeout; error kept, never zeros |\n| `reader-about` | brew/reader/stages/open.js:218 | About text from the site | Sonnet, Flash | none beyond schema |\n| `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 [src: memory brew-external-data-skill] |\n| `reader-rivals-alt`, `reader-rivals-known` | brew/reader/stages/ads.js:113 and 120 | More rivals when fewer than 3 | Sonnet, Flash | same |\n| `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 [src: memory brew-proof-plain-make] |\n| `brandbook-read` | brew/brand-book-read.js:282 | Brand Book story, voice, words, claims, look | Sonnet low, Flash | Book verify |\n| untagged `claude()` calls | brew/research.js:167-445 | Stories: rival ad notes, interests, trends, how-to, news | Jam params, Flash | Honest numbers |\n| `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 |\n\n### Build: brief, Plays, cards\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| `brief` | brew/brief.js:108 | The brand brief every Play reads | Opus high, Flash | Fact gate |\n| `move00` | brew/moves-engine.js:652 | The index Play | Plays tier, Pro | Claims rule in the prompt, Mark |\n| `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 [src: brew/moves-engine.js:471-473] |\n| `moveNN-retry`, `moveNN-whole` | brew/moves-engine.js:476-490 | A Play that failed or came back cut | Plays tier, effort low | same |\n| `verifyNN` | brew/moves-engine.js:553 | Checks each Play against the lines it cites | Sonnet low, Flash | is itself the guard |\n| `fixNN` | brew/moves-engine.js:568 | Rewrites only flagged lines; unbacked numbers become labelled targets | Sonnet medium, Flash | Play check again |\n| `moves-<family>` | brew/moves-cadence.js:387 | Weekly cadence Plays | Sonnet medium, Flash | Honest, fact gate |\n| `move-value` | brew/value.js:62 | Grades the value of each Play | Sonnet, Flash | Schema |\n| `cards` | brew/cards-gen.js:273 | Feed cards written from Plays and reads | Sonnet, Flash | Fact gate strict, Claims, Check copy |\n| `cards-claims` | brew/cards-gen.js:326 | Rewrites a card whose claims failed | Sonnet, Flash | Claims |\n| `cards-read` | brew/cards-gen.js:345 | Cards from the read's findings | Sonnet, Flash | Fact gate, Check copy |\n| `plain_cards` | brew/plain.js:164 | Plain-words rewrite of every card, 12 at a time | Jam, Flash | Numbers checked in code, Claims [src: memory brew-proof-plain-make] |\n| `notes` | brew/notes.js:54 | Team notes | Sonnet, Flash | Schema |\n| `statics` | brew/statics.js:103 | Static ad words | Sonnet, Flash | Claims rule, Check copy, fact gate |\n| `ideas:slate` | brew/ideas.js:382 | Which ideas to write | Opus medium, Flash | Honest |\n| `ideas:write` | brew/ideas.js:400 | The ideas themselves | Opus high, Flash | Claims, Check copy, fact gate |\n| `ideas:check` | brew/ideas.js:524 | A second read of the ideas | Sonnet, Flash | is itself the guard |\n| `refresh-triage` | brew/refresh.js:122 | Which Plays a site change affects | Sonnet, Flash | Feeds the capped rewrite pot |\n| `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 |\n| `pulse-questions-<slug>` | brew/market-pulse.js:65 | Weekly market questions | Sonnet, Flash | Schema |\n| `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 |\n| `measure-family`, propose | brew/measure-families.js:108 and 149 | Which measurement family a card belongs to | Jam, Flash | Enum of known families |\n| `facts-link` | brew/facts-desk.js:214 | Links a fact to its source | Sonnet, Flash | Numbers |\n\n### Learning and memory\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| `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 |\n| `memory-extract`, `memory-decide`, `memory-learn`, `memory-dream` | brew/brand-memory.js:158, 164, 407, 445 | Brand memory | Sonnet, Flash | Schema |\n| `drop-read` | brew/drop-read.js:83 and 88 | Reads anything dropped into Brew | Sonnet low, Flash | Schema |\n| `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 |\n| `pref-sides` | brew/feed-service.js:1980 | Preferences from a dropped text | Jam, Flash | Schema |\n| `learn` | brew/feed-service.js:1671 | A lesson from a step the person took | Jam, Flash | Schema |\n| map wants | brew/feed-service.js:1743 | Maps what a founder said to card types | Jam JSON, Flash | none beyond parse |\n\n### Feed, jam and chat\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| scheduled idea card | brew/feed-service.js:949 | One new ad idea card on a schedule | Jam JSON, Flash | Check copy downstream |\n| more like this | brew/feed-service.js:1223 | A new card in the direction of a hearted one | Jam JSON, Flash | Fact gate, Claims |\n| route | brew/feed-service.js:1239 | Sends a message to AI or to a person on our team | Jam JSON, Flash | Enum |\n| `versions` | brew/feed-service.js:1252 | One new version of a card | Jam, Flash | Fact gate, Claims |\n| sort message | brew/feed-service.js:1574 | Sorts a chat message: chat, question, change, make, yes, no | Jam, Flash | Enum |\n| `colleague` | brew/feed-service.js:1606 | A reply in Slack as a role | Jam, Flash | Check copy |\n| `jam_answer` | brew/jam-answer.js:79 | Grounded answer to a question, from evidence | Jam, Flash | Claims; says \"I don't know\" when unknown |\n| `canvas` | brew/feed-service.js:1693 | Picks the blocks that show the work | Jam, Flash | Enum of blocks |\n| `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 |\n| `draft` | brew/drafts.js:81 | A draft from a card | Jam, Flash | Claims rule, Copy rule, Clean |\n| `draft-bg` | brew/drafts-bg.js:224 | First drafts made with nobody watching | Sonnet, Flash | Clean, fact gate |\n| `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 |\n| `jam_doc` | brew/jam-brief.js:214 | Rewrites the jam brief as asked | Jam, Flash | Check copy |\n| jam question | brew/jam-brief.js:294 | Answers a question in the brief | Jam, Flash | Grounded answer |\n| `team_brief`, `team_brief_edit` | brew/team-brief.js:90 and 175 | The brief sent to an agency or team | Jam, Flash | Check copy |\n| `remix_options` | brew/remix.js:633 | The package a jam makes | Jam, Flash | Claims rule, Copy rule |\n| `remix_mend` | brew/remix.js:644 | Rewrites a package once on its slips | Jam, Flash | Slips and mend |\n| jam chat answer | brew/remix.js:1051 | Answers in the jam room | Jam, Flash | Grounded answer, Proof |\n| `studio_iterate` | brew/remix.js:1072 | An edit to the package | Jam, Flash | Check copy |\n| `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 |\n| `v2_words` | brew/remix.js:1495 | Rewrites only the words | Jam, Flash | Copy rule |\n| `impact` | brew/remix.js:1963 | Expected impact of a change | Jam, Flash | Inputs built in code |\n| `remake` | brew/remix.js:1999 | Our version of a rival ad or viral video | Jam, Flash | The rival's words are never reused |\n| named stage | brew/server.js:444 | Brands named in saved AI answers | Sonnet, Flash | Schema |\n\n### Studio\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| `jam2_direct` | brew/jam2/creative.js:78 | Art direction: format, moment, calm zone | Jam, Flash | Brand Book look and people rules |\n| `jam2_critic` | brew/jam2/creative.js:105 | Vision check of each shot against the product | Sonnet low, Flash | is itself the guard |\n| `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 |\n| `jam2_write` | brew/jam2/make.js:94 | Headline, caption, script for a board | Jam, Flash | Claims, banned words |\n| `jam2_headline` | brew/jam2/make.js:98 | A headline when the writer left it empty | Jam, Flash | 7 words at most |\n| `jam2_places` | brew/jam2/make.js:267 | Empty settings for video shots | Jam, Flash | No product drawn by AI |\n| `jam2_line` | brew/jam2/make.js:484 | Rewrites one line | Jam, Flash | \"Same facts only\" in the prompt |\n| `product_profile` | brew/jam2/profiles.js:40 | What a product is, label, size | Sonnet low, Flash | Schema |\n| `studio_ask` | brew/jam2/routes.js:202 | Turns a request into set-up changes | Jam, Flash | Change only what was asked |\n\n### Pictures and video checks\n\n| Tag | Where | Feeds | Tier | Guard |\n|---|---|---|---|---|\n| product check | brew/server.js:220-230 | SAME, TEXT, DIFFERENT or NOREF for every generated picture | Haiku, Flash | is itself the guard |\n| 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 |\n| `video_text_check` | brew/text-check.js:34-50 | On-screen words of a video final read back | Jam, Flash | is itself the guard |\n| 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 |\n|---|---|---|\n| Every tag listed in one data file with tier, effort, max tokens and guard; the code reads it | v2 | New |\n| A test that fails when a call site has no tag or no listed guard | v1 | New |\n| Jam calls metered in dollars like ai.js calls | v1 | Changes |\n| Untagged research.js and live-watch.js calls get tags | v1 | Changes |\n| Prompts kept in prompts/ files where long, so a prompt change shows in review | v2 | Changes |\n| Writers that post or schedule for the brand get the same guards plus a send gate | v2 | New |",
  "How we do it": "1. Rebuild this list from origin/main:\n   ```bash\n   cd /Users/param/Documents/ChatGPT/brew\n   git grep -n -E 'claudeTool\\(|ai\\.call\\(|claudeJSON\\(' origin/main -- '*.js' ':!test/*' ':!public/*'\n   git grep -n -E \"tag: *['\\`]\" origin/main -- '*.js' ':!test/*' ':!public/*' | grep -v treg\n   ```\n2. 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.\n3. Every writer prompt that a shopper may read carries `CLAIMS_RULE` and `COPY_RULE` [src: brew/claims.js:88] [src: brew/claims.js:196].\n4. Every output a shopper may copy goes through `checkCopy` or `checkCopyIn` [src: brew/claims.js:215-232].\n5. Update this document in the same change.",
  "Numbers": "| Metric | Definition | Where measured | Status |\n|---|---|---|---|\n| Call sites | Count of AI call sites on origin/main | the grep above; about 98 on 26 Oct | Live |\n| Unguarded sites | Sites that feed a shopper-facing surface with no guard | this table | Proposed, target 0 |\n| Spend by tag | Dollars per tag per day | ai.js `meter.byTag` [src: brew/ai.js:51] | Live, not reported |",
  "Open": "1. **Should the registry become code?** Proposal: yes, a `data/prompts.json` read by ai.js and server.js, in v2, with a test that every call site is listed.\n2. **Which tags need a stronger tier first?** Proposal: brief and `ideas:write` move to Pro with the Plays, because they asked for Opus and every Play reads the brief."
 }
}