CLI command
glossary
A product's banned phrases, checked in drafts and enforced when a blog post is published.
Invocation#
echo-cli glossary list --product <id>
echo-cli glossary ban --product <id> --phrase <text> [--instead <text>] --by <name>
echo-cli glossary lift --id <banned-phrase-id>
echo-cli glossary check --product <id> [--text <text>] [--file <path>]
echo-cli glossary surface --surface <slug> --product <id>Inputs and output#
list writes the product's banned phrases alphabetically: id, product_id, phrase, use_instead (null when nothing replaces it), created_by and created_at. ban and lift write the phrase they banned or lifted. check writes every occurrence as phrase, use_instead, field (text for --text, body for --file), line and column, an empty list when the text is clean. surface writes the surface's slug and the product it now answers to.
State effect#
Every verb calls Echo Web's authenticated /api/analytics/glossary, /glossary/check or /glossary/surfaces with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the Brand glossary section of the blog admin and the Brand glossary section of Echo Desktop's GEO screen call the same operations, and echo-mcp reads the phrases (echo_list_banned_phrases) and checks drafts (echo_check_glossary) but cannot ban or lift. A phrase matches without regard to case and only as whole words, so a banned word inside a longer word is not an occurrence; a phrase is banned once per product whatever its case. check exits 1 when it finds any occurrence, so a script can stop before publishing. Publishing a blog post, from the blog admin or through an approved publication, and editing a post that is already published, check its title, description and body against the glossary of the product its surface names and refuse the post with every occurrence; a surface that names no product cannot publish until surface names one. The post is then published or edited only as it was checked. The generators check what they write before it is kept: a blog generation run whose draft holds a banned phrase of its surface's product ends failed with error "the draft uses banned phrases of the surface's product: <every occurrence>" and its draft kept for editing; viral-format adaptations (content adapt), ghostwritten drafts of a branded account and short-video scripts (content scripts) are refused as unprocessable and nothing is kept; repurposed formats are left undrafted with the occurrences as their error; and a CRM campaign that speaks for a product (email brand) sends no message holding one, the recipient failed with error "banned_phrases: <every occurrence>".
Refusals#
- A wrong invocation is refused before anything is sent: "glossary takes <every verb's usage, separated by semicolons>; got <word>", "glossary <verb> does not take <flag>; it takes …", "<flag> needs a value", "glossary <verb> needs <flag>" for each flag the verb needs, and "glossary check needs --text <text> or --file <path>: the text to check"; a --file that cannot be read ends with the system's error naming the path.
- Echo Web answers a bad request with "product_id is required: …", "phrase is required: the words the product's texts may not use", "use_instead must be what to write instead, or null when nothing replaces the phrase", "fields is required: the text to check, as [{ field, text }]", "surface is required: …" or "created_by is required: an internal caller has no signed-in user, so it names who is acting"; not found with "no product has id <id>; echo-cli products lists the ones that exist", "no banned phrase has id <id>; echo-cli glossary list --product <id> lists them" or "no blog surface has slug <slug>"; and a conflict with "product <id> already bans \"<phrase>\"". Publishing answers "the post uses banned phrases: \"<phrase>\" in <field> at line <n>, column <n>; write \"<text>\" instead; …" as unprocessable with the list under violations, and "blog surface <slug> names no product, so no glossary says what its posts may not say; echo-cli glossary surface --surface <slug> --product <id> names it" as a bad request.