"""Natural-language control phrases for Universal Brain chat. This is a lightweight, deterministic pre-router for actions that should not depend on LLM JSON routing (and should work without requiring users to remember slash commands). It is intentionally conservative: it only triggers on fairly explicit phrasing. """ from __future__ import annotations from dataclasses import dataclass import re @dataclass(frozen=True) class ControlAction: name: str value: str | None = None _WS = re.compile(r"\s+") def _norm(s: str) -> str: return _WS.sub(" ", (s or "").strip().lower()) def parse_control_action(message: str) -> ControlAction | None: """Return a ControlAction if the message is a natural-language control request.""" m = _norm(message) if not m: return None # "What mode is this? What session/scope am I in?" if re.search(r"\b(what|show)\b.*\b(my )?(session|scope|settings|mode|status)\b", m) or re.search( r"\bwhich\b.*\b(scope|session)\b", m ): return ControlAction("show_session") # Start a fresh private session (new scope key). if re.search(r"\b(new|fresh)\b.*\b(private )?(session|scope)\b", m) or re.search( r"\b(start|begin)\b.*\b(private )?(session|scope)\b", m ): return ControlAction("new_private_session") # Switch to a named scope in chat, e.g. "use scope abc-123" / "switch to session foo". m2 = re.search(r"\b(use|switch to|set)\b.*\b(scope|session)\b\s*[:=]?\s*([a-z0-9][a-z0-9_.:-]{1,63})\b", m) if m2: return ControlAction("set_scope", m2.group(3)) # Memory controls (order matters: list/show before export/download) if re.search( r"\b(show|list)\b.*\b(my )?(data|memory|memories|notes)\b", m, ): return ControlAction("list_memories") if re.search( r"\b(export|download)\b.*\b(my )?(data|memory|memories|notes)\b", m, ): return ControlAction("export_memory") if re.search(r"\b(clear|wipe|delete|forget)\b.*\b(session)\b.*\b(memory|memories|notes)?\b", m): return ControlAction("clear_session") if re.search(r"\b(forget|delete|erase|wipe)\b.*\b(all|everything)\b.*\b(memory|memories|notes|data)\b", m) or re.search( r"\b(delete|erase)\b.*\b(my )?(data|account data|data for this chat)\b", m ): return ControlAction("forget_scope") # Session toggles (chat UX) — short lines only so long questions are not hijacked # (e.g. "Show the brain trace. … outline a stakeholder map …" must stay normal chat). if len(m) <= 120: if re.search(r"\b(turn on|enable|show)\b.*\b(trace|brain trace|debug)\b", m): return ControlAction("set_trace", "on") if re.search(r"\b(turn off|disable|hide)\b.*\b(trace|brain trace|debug)\b", m): return ControlAction("set_trace", "off") if re.search(r"\b(turn on|enable)\b.*\b(smart routing|auto routing|router)\b", m): return ControlAction("set_smart_route", "on") if re.search(r"\b(turn off|disable)\b.*\b(smart routing|auto routing|router)\b", m): return ControlAction("set_smart_route", "off") if re.search(r"\b(turn on|enable)\b.*\b(faq|rag|retrieval)\b", m): return ControlAction("set_rag", "on") if re.search(r"\b(turn off|disable)\b.*\b(faq|rag|retrieval)\b", m): return ControlAction("set_rag", "off") # Reply style for the generative model (short lines only to avoid hijacking real questions). # Require "reply"/"answer" before style|format|length so phrases like "default quote style" / "reset tables" # are handled by narrower matchers below. if len(m) <= 140 and ( re.search(r"\breset\b.*\b(reply|answer)\s+(style|format|length)\b", m) or re.search(r"\b(default|normal)\b.*\b(reply|answer)\s+(style|format|length)\b", m) ): return ControlAction("reset_reply_style") if len(m) <= 96 and re.search( r"\b(be brief|stay brief|keep it short|short answers|answer briefly|concise replies)\b", m, ): return ControlAction("set_verbosity", "brief") if len(m) <= 120 and re.search( r"\b(more detail|go deeper|in greater detail|explain thoroughly|longer answers|detailed answers)\b", m, ): return ControlAction("set_verbosity", "detailed") if len(m) <= 100 and re.search( r"\b(normal (answer )?length|default length|balanced length)\b", m, ): return ControlAction("set_verbosity", "normal") if len(m) <= 110 and re.search(r"\b(use|prefer)\b", m) and re.search( r"\b(bullet points?|numbered lists?)\b", m, ): return ControlAction("set_reply_format", "bullets") if len(m) <= 100 and re.search( r"\b(no bullets|plain paragraphs?|prose only|stop using lists)\b", m, ): return ControlAction("set_reply_format", "prose") # FAQ / RAG grounding hints for the assistant (short control lines). if len(m) <= 100 and re.search( r"\b(strict faq|faq only|stick to (the )?faq|only use (the )?faq|only trust (the )?faq)\b", m, ): return ControlAction("set_faq_grounding", "strict") if len(m) <= 115 and re.search( r"\b(balanced faq|normal faq|default faq(\s+grounding)?|default faq mode)\b", m, ): return ControlAction("set_faq_grounding", "normal") if len(m) <= 130 and re.search( r"\b(relaxed faq|faq plus general knowledge|general knowledge(\s+is)?\s+ok|mix faq and general knowledge)\b", m, ): return ControlAction("set_faq_grounding", "relaxed") # Explanation depth (who the answer is for) — short control lines only. if ( (len(m) <= 40 and re.match(r"^(please\s+)?explain simply[\s.!?]*$", m)) or re.match(r"^(please\s+)?eli5\b[\s.!?]*$", m) or (len(m) <= 56 and re.search(r"\b(i'?m\s+a\s+beginner|beginner\s+here)\b", m)) or re.match(r"^(please\s+)?assume i'?m\s+new\b[\s.!?]*$", m) or (len(m) <= 56 and re.search(r"\bi\s+need\s+(the\s+)?basics\b", m)) ): return ControlAction("set_audience", "simple") if len(m) <= 72 and ( re.match(r"^(please\s+)?assume i'?m\s+technical[\s.!?]*$", m) or re.match(r"^expert\s+mode[\s.!?]*$", m) or re.match(r"^(please\s+)?use jargon freely[\s.!?]*$", m) or re.match(r"^technical audience[\s.!?]*$", m) or re.match(r"^for experts[\s.!?]*$", m) ): return ControlAction("set_audience", "technical") if len(m) <= 78 and ( re.match(r"^(please\s+)?(default explanation level|normal explanation level|general audience)[\s.!?]*$", m) or re.match(r"^(please\s+)?(reset|default)\s+audience[\s.!?]*$", m) ): return ControlAction("set_audience", "normal") # Answer lead — whether to front-load a TL;DR line (orthogonal to verbosity). if len(m) <= 88 and ( re.match(r"^(please\s+)?(tl;|tl)dr\s+first\b[\s.!?]*$", m) or re.match(r"^(please\s+)?(lead|start)\s+with\s+(a\s+)?(short\s+)?summary\b[\s.!?]*$", m) or re.match(r"^(please\s+)?summary\s+first\b[\s.!?]*$", m) ): return ControlAction("set_answer_lead", "tldr_first") if len(m) <= 92 and ( re.match(r"^(please\s+)?no\s+tl;?dr\b[\s.!?]*$", m) or re.match(r"^(please\s+)?skip (the\s+)?summary\b[\s.!?]*$", m) or re.match(r"^(please\s+)?answer directly\b[\s.!?]*$", m) or re.match(r"^(please\s+)?direct answer\s+only\b[\s.!?]*$", m) or re.match(r"^(please\s+)?without\s+a\s+tldr\b[\s.!?]*$", m) ): return ControlAction("set_answer_lead", "direct") if len(m) <= 64 and ( re.match(r"^(please\s+)?(default answer structure|normal answer opening|usual\s+opening)[\s.!?]*$", m) or re.match(r"^(please\s+)?reset\s+(answer\s+)?opening[\s.!?]*$", m) ): return ControlAction("set_answer_lead", "normal") # Procedures: numbered steps vs continuous prose (orthogonal to bullets). if len(m) <= 88 and ( re.match(r"^(please\s+)?(step by step|step-by-step)[\s.!?]*$", m) or re.match(r"^(please\s+)?use numbered steps[\s.!?]*$", m) or re.match(r"^(please\s+)?numbered steps\b[\s.!?]*$", m) or re.match(r"^(please\s+)?walk me through( the)? steps\b[\s.!?]*$", m) or re.match(r"^(please\s+)?break it into steps[\s.!?]*$", m) ): return ControlAction("set_step_style", "numbered") if len(m) <= 92 and ( re.match(r"^(please\s+)?(no numbered steps|don'?t number steps|skip step numbers)[\s.!?]*$", m) or re.match(r"^(please\s+)?(continuous prose|prose without steps)[\s.!?]*$", m) ): return ControlAction("set_step_style", "continuous") if len(m) <= 64 and re.match(r"^(please\s+)?(default step style|normal steps|reset steps)[\s.!?]*$", m): return ControlAction("set_step_style", "normal") # How hard to hedge / flag limits (orthogonal to FAQ strictness). if len(m) <= 94 and ( re.match(r"^(please\s+)?flag your assumptions[\s.!?]*$", m) or re.match(r"^(please\s+)?be explicit about uncertainty[\s.!?]*$", m) or re.match(r"^(please\s+)?say if you don'?t know[\s.!?]*$", m) or re.match(r"^(please\s+)?tell me when you(?:'?re|\s+are)\s+unsure[\s.!?]*$", m) or re.match(r"^(please\s+)?say when you(?:'?re|\s+are)\s+unsure[\s.!?]*$", m) ): return ControlAction("set_confidence_tone", "transparent") if len(m) <= 72 and ( re.match(r"^(please\s+)?be decisive[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t hedge[\s.!?]*$", m) or re.match(r"^(please\s+)?give firm answers[\s.!?]*$", m) ): return ControlAction("set_confidence_tone", "assertive") if len(m) <= 80 and re.match( r"^(please\s+)?(default confidence tone|normal confidence|reset uncertainty)[\s.!?]*$", m, ): return ControlAction("set_confidence_tone", "normal") # Whether to offer follow-ups / next steps at the end of answers. if len(m) <= 96 and ( re.match(r"^(please\s+)?suggest next steps[\s.!?]*$", m) or re.match(r"^(please\s+)?offer follow[- ]up questions[\s.!?]*$", m) or re.match(r"^(please\s+)?end with (optional )?next steps[\s.!?]*$", m) ): return ControlAction("set_followup_close", "suggest") if len(m) <= 100 and ( re.match(r"^(please\s+)?no follow[- ]up questions[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t ask follow[- ]up questions[\s.!?]*$", m) or re.match(r"^(please\s+)?no questions at the end[\s.!?]*$", m) ): return ControlAction("set_followup_close", "minimal") if len(m) <= 78 and ( re.match(r"^(please\s+)?(default follow[- ]ups?|reset follow[- ]ups?|normal follow[- ]ups?)[\s.!?]*$", m) ): return ControlAction("set_followup_close", "normal") # Teach order: define terms vs motivate first (orthogonal to TL;DR / steps). if len(m) <= 80 and ( re.match(r"^(please\s+)?definitions first[\s.!?]*$", m) or re.match(r"^(please\s+)?start with definitions[\s.!?]*$", m) or re.match(r"^(please\s+)?define terms first[\s.!?]*$", m) ): return ControlAction("set_exposition_order", "definitions_first") if len(m) <= 96 and ( re.match(r"^(please\s+)?intuition first[\s.!?]*$", m) or re.match(r"^(please\s+)?big picture first[\s.!?]*$", m) or re.match(r"^(please\s+)?start with the big picture[\s.!?]*$", m) ): return ControlAction("set_exposition_order", "intuition_first") if len(m) <= 88 and re.match( r"^(please\s+)?(default explanation order|reset explanation order|normal explanation order)[\s.!?]*$", m, ): return ControlAction("set_exposition_order", "normal") # Examples vs terse explanations when comparing or teaching. if len(m) <= 76 and ( re.match(r"^(please\s+)?include examples[\s.!?]*$", m) or re.match(r"^(please\s+)?use concrete examples[\s.!?]*$", m) or re.match(r"^(please\s+)?illustrate with examples[\s.!?]*$", m) ): return ControlAction("set_example_density", "rich") if len(m) <= 92 and ( re.match(r"^(please\s+)?skip examples[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t add examples[\s.!?]*$", m) or re.match(r"^(please\s+)?no examples unless i ask[\s.!?]*$", m) ): return ControlAction("set_example_density", "sparse") if len(m) <= 68 and re.match( r"^(please\s+)?(default examples|normal examples|reset examples)[\s.!?]*$", m, ): return ControlAction("set_example_density", "normal") # Compare/contrast presentation. if len(m) <= 96 and ( re.match(r"^(please\s+)?use pros and cons[\s.!?]*$", m) or re.match(r"^(please\s+)?pros and cons sections[\s.!?]*$", m) or re.match(r"^(please\s+)?compare with pros and cons[\s.!?]*$", m) ): return ControlAction("set_comparison_frame", "pros_cons") if len(m) <= 100 and ( re.match(r"^(please\s+)?compare in flowing prose[\s.!?]*$", m) or re.match(r"^(please\s+)?prose comparison only[\s.!?]*$", m) or re.match(r"^(please\s+)?no pros and cons sections[\s.!?]*$", m) ): return ControlAction("set_comparison_frame", "narrative") if len(m) <= 82 and re.match( r"^(please\s+)?(default comparison style|normal comparison|reset comparison)[\s.!?]*$", m, ): return ControlAction("set_comparison_frame", "normal") # Professional vs conversational wording (orthogonal to verbosity). if len(m) <= 92 and ( re.match(r"^(please\s+)?formal tone[\s.!?]*$", m) or re.match(r"^(please\s+)?professional register[\s.!?]*$", m) or re.match(r"^(please\s+)?business writing style[\s.!?]*$", m) ): return ControlAction("set_register_tone", "formal") if len(m) <= 96 and ( re.match(r"^(please\s+)?casual tone[\s.!?]*$", m) or re.match(r"^(please\s+)?friendly casual style[\s.!?]*$", m) or re.match(r"^(please\s+)?speak casually[\s.!?]*$", m) ): return ControlAction("set_register_tone", "casual") if len(m) <= 76 and re.match( r"^(please\s+)?(default tone|neutral tone|reset tone)[\s.!?]*$", m, ): return ControlAction("set_register_tone", "normal") # Markdown code snippet layout. if len(m) <= 100 and ( re.match(r"^(please\s+)?use code fences[\s.!?]*$", m) or re.match(r"^(please\s+)?fenced code blocks[\s.!?]*$", m) or re.match(r"^(please\s+)?markdown code fences[\s.!?]*$", m) ): return ControlAction("set_code_block_style", "fenced") if len(m) <= 104 and ( re.match(r"^(please\s+)?inline code only[\s.!?]*$", m) or re.match(r"^(please\s+)?no triple backticks[\s.!?]*$", m) or re.match(r"^(please\s+)?no fenced code blocks[\s.!?]*$", m) ): return ControlAction("set_code_block_style", "inline") if len(m) <= 96 and re.match( r"^(please\s+)?(default code formatting|reset code style|normal code blocks)[\s.!?]*$", m, ): return ControlAction("set_code_block_style", "normal") # Analogies / metaphors vs literal explanations only. if len(m) <= 92 and ( re.match(r"^(please\s+)?use analogies[\s.!?]*$", m) or re.match(r"^(please\s+)?analogies when helpful[\s.!?]*$", m) or re.match(r"^(please\s+)?metaphors are ok[\s.!?]*$", m) ): return ControlAction("set_analogy_use", "prefer") if len(m) <= 100 and ( re.match(r"^(please\s+)?no analogies[\s.!?]*$", m) or re.match(r"^(please\s+)?skip metaphors[\s.!?]*$", m) or re.match(r"^(please\s+)?literal explanations only[\s.!?]*$", m) ): return ControlAction("set_analogy_use", "avoid") if len(m) <= 82 and re.match( r"^(please\s+)?(default analogy style|reset analogies|normal analogies)[\s.!?]*$", m, ): return ControlAction("set_analogy_use", "normal") # Expand vs terse acronym handling on first introduce. if len(m) <= 112 and ( re.match(r"^(please\s+)?spell out acronyms[\s.!?]*$", m) or re.match(r"^(please\s+)?expand acronyms on first use[\s.!?]*$", m) or re.match(r"^(please\s+)?define acronyms when you use them[\s.!?]*$", m) ): return ControlAction("set_acronym_style", "spell_out") if len(m) <= 112 and ( re.match(r"^(please\s+)?assume i know acronyms[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t expand acronyms[\s.!?]*$", m) or re.match(r"^(please\s+)?keep acronyms as is[\s.!?]*$", m) ): return ControlAction("set_acronym_style", "terse") if len(m) <= 92 and re.match( r"^(please\s+)?(default acronym style|reset acronyms|normal acronyms)[\s.!?]*$", m, ): return ControlAction("set_acronym_style", "normal") # Clarify-first: ask brief questions before answering if key info is missing. if len(m) <= 110 and ( re.match(r"^(please\s+)?ask clarifying questions first[\s.!?]*$", m) or re.match(r"^(please\s+)?clarify first[\s.!?]*$", m) or re.match(r"^(please\s+)?ask me questions before answering[\s.!?]*$", m) ): return ControlAction("set_clarify_first", "on") if len(m) <= 110 and ( re.match(r"^(please\s+)?no clarifying questions[\s.!?]*$", m) or re.match(r"^(please\s+)?just answer without questions[\s.!?]*$", m) or re.match(r"^(please\s+)?answer without asking questions[\s.!?]*$", m) ): return ControlAction("set_clarify_first", "off") if len(m) <= 96 and re.match( r"^(please\s+)?(default clarify mode|reset clarify mode|normal clarify mode)[\s.!?]*$", m, ): return ControlAction("set_clarify_first", "normal") # Speculation level: strict factual vs brainstorming. if len(m) <= 110 and ( re.match(r"^(please\s+)?no speculation[\s.!?]*$", m) or re.match(r"^(please\s+)?stick to high confidence only[\s.!?]*$", m) or re.match(r"^(please\s+)?avoid guessing[\s.!?]*$", m) ): return ControlAction("set_speculation", "strict") if len(m) <= 110 and ( re.match(r"^(please\s+)?brainstorm freely[\s.!?]*$", m) or re.match(r"^(please\s+)?speculate freely[\s.!?]*$", m) or re.match(r"^(please\s+)?wild ideas ok[\s.!?]*$", m) ): return ControlAction("set_speculation", "creative") if len(m) <= 100 and re.match( r"^(please\s+)?(default speculation|normal speculation|reset speculation)[\s.!?]*$", m, ): return ControlAction("set_speculation", "normal") # Math/explanations: show work vs final-only. if len(m) <= 110 and ( re.match(r"^(please\s+)?show your work[\s.!?]*$", m) or re.match(r"^(please\s+)?show the derivation[\s.!?]*$", m) or re.match(r"^(please\s+)?include steps in math[\s.!?]*$", m) ): return ControlAction("set_math_detail", "show_work") if len(m) <= 110 and ( re.match(r"^(please\s+)?final answer only[\s.!?]*$", m) or re.match(r"^(please\s+)?no derivation[\s.!?]*$", m) or re.match(r"^(please\s+)?skip the steps[\s.!?]*$", m) ): return ControlAction("set_math_detail", "final_only") if len(m) <= 110 and re.match( r"^(please\s+)?(default math detail|normal math detail|reset math detail)[\s.!?]*$", m, ): return ControlAction("set_math_detail", "normal") # Output structure: JSON-shaped vs normal prose. if len(m) <= 110 and ( re.match(r"^(please\s+)?answer in json[\s.!?]*$", m) or re.match(r"^(please\s+)?json output[\s.!?]*$", m) or re.match(r"^(please\s+)?structured json[\s.!?]*$", m) ): return ControlAction("set_output_format", "json") if len(m) <= 110 and ( re.match(r"^(please\s+)?plain text only[\s.!?]*$", m) or re.match(r"^(please\s+)?no json[\s.!?]*$", m) or re.match(r"^(please\s+)?no structured output[\s.!?]*$", m) ): return ControlAction("set_output_format", "plain") if len(m) <= 110 and re.match( r"^(please\s+)?(default output format|normal output format|reset output format)[\s.!?]*$", m, ): return ControlAction("set_output_format", "normal") # Safety/risk posture for recommendations. if len(m) <= 110 and ( re.match(r"^(please\s+)?be risk averse[\s.!?]*$", m) or re.match(r"^(please\s+)?be conservative[\s.!?]*$", m) or re.match(r"^(please\s+)?err on the side of safety[\s.!?]*$", m) ): return ControlAction("set_risk_posture", "conservative") if len(m) <= 110 and ( re.match(r"^(please\s+)?be pragmatic[\s.!?]*$", m) or re.match(r"^(please\s+)?optimize for speed[\s.!?]*$", m) or re.match(r"^(please\s+)?good enough is fine[\s.!?]*$", m) ): return ControlAction("set_risk_posture", "pragmatic") if len(m) <= 110 and re.match( r"^(please\s+)?(default risk posture|normal risk posture|reset risk posture)[\s.!?]*$", m, ): return ControlAction("set_risk_posture", "normal") # Actionability: runnable steps vs conceptual explanation. if len(m) <= 110 and ( re.match(r"^(please\s+)?give me runnable commands[\s.!?]*$", m) or re.match(r"^(please\s+)?include commands[\s.!?]*$", m) or re.match(r"^(please\s+)?make it actionable[\s.!?]*$", m) ): return ControlAction("set_actionability", "commands") if len(m) <= 110 and ( re.match(r"^(please\s+)?no commands[\s.!?]*$", m) or re.match(r"^(please\s+)?conceptual only[\s.!?]*$", m) or re.match(r"^(please\s+)?high level only[\s.!?]*$", m) ): return ControlAction("set_actionability", "conceptual") if len(m) <= 110 and re.match( r"^(please\s+)?(default actionability|normal actionability|reset actionability)[\s.!?]*$", m, ): return ControlAction("set_actionability", "normal") # Quote/citation preference when using supplied excerpts. if len(m) <= 110 and ( re.match(r"^(please\s+)?quote the faq excerpts[\s.!?]*$", m) or re.match(r"^(please\s+)?use direct quotes[\s.!?]*$", m) or re.match(r"^(please\s+)?cite with quotes[\s.!?]*$", m) ): return ControlAction("set_quote_style", "quote") if len(m) <= 110 and ( re.match(r"^(please\s+)?no quotes[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t quote excerpts[\s.!?]*$", m) or re.match(r"^(please\s+)?paraphrase only[\s.!?]*$", m) ): return ControlAction("set_quote_style", "paraphrase") if len(m) <= 110 and re.match( r"^(please\s+)?(default quote style|normal quote style|reset quote style)[\s.!?]*$", m, ): return ControlAction("set_quote_style", "normal") # Tables: prefer markdown tables vs avoid. if len(m) <= 110 and ( re.match(r"^(please\s+)?use tables[\s.!?]*$", m) or re.match(r"^(please\s+)?markdown tables[\s.!?]*$", m) or re.match(r"^(please\s+)?tabular format[\s.!?]*$", m) ): return ControlAction("set_table_style", "prefer") if len(m) <= 110 and ( re.match(r"^(please\s+)?no tables[\s.!?]*$", m) or re.match(r"^(please\s+)?avoid tables[\s.!?]*$", m) or re.match(r"^(please\s+)?no markdown tables[\s.!?]*$", m) ): return ControlAction("set_table_style", "avoid") if len(m) <= 110 and re.match( r"^(please\s+)?(default table style|normal tables|reset tables)[\s.!?]*$", m, ): return ControlAction("set_table_style", "normal") # Emoji in assistant replies (short lines; conservative wording). if len(m) <= 110 and ( re.match(r"^(please\s+)?(use emoji|emoji ok|emoji welcome|include emoji)[\s.!?]*$", m) or re.match(r"^(please\s+)?add (a few )?emoji[\s.!?]*$", m) ): return ControlAction("set_emoji_style", "include") if len(m) <= 110 and ( re.match(r"^(please\s+)?no emojis?[\s.!?]*$", m) or re.match(r"^(please\s+)?avoid emoji[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t use emoji[\s.!?]*$", m) ): return ControlAction("set_emoji_style", "avoid") if len(m) <= 110 and re.match( r"^(please\s+)?(default emoji style|normal emoji|reset emoji)[\s.!?]*$", m, ): return ControlAction("set_emoji_style", "normal") # Markdown section headings (## / ###) vs flat prose. if len(m) <= 110 and ( re.match(r"^(please\s+)?use section headings[\s.!?]*$", m) or re.match(r"^(please\s+)?organize with headings[\s.!?]*$", m) or re.match(r"^(please\s+)?use markdown headings[\s.!?]*$", m) ): return ControlAction("set_section_headings", "prefer") if len(m) <= 110 and ( re.match(r"^(please\s+)?no section headings[\s.!?]*$", m) or re.match(r"^(please\s+)?avoid markdown headings[\s.!?]*$", m) or re.match(r"^(please\s+)?flat (answer|prose)( please)?[\s.!?]*$", m) ): return ControlAction("set_section_headings", "avoid") if len(m) <= 110 and re.match( r"^(please\s+)?(default section headings|normal headings|reset headings)[\s.!?]*$", m, ): return ControlAction("set_section_headings", "normal") # Inline emphasis: bold a few key terms vs keep markdown minimal. if len(m) <= 110 and ( re.match(r"^(please\s+)?bold key terms[\s.!?]*$", m) or re.match(r"^(please\s+)?highlight important terms[\s.!?]*$", m) or re.match(r"^(please\s+)?emphasize keywords[\s.!?]*$", m) ): return ControlAction("set_term_emphasis", "highlight") if len(m) <= 110 and ( re.match(r"^(please\s+)?minimal bold[\s.!?]*$", m) or re.match(r"^(please\s+)?don'?t overuse bold[\s.!?]*$", m) or re.match(r"^(please\s+)?avoid excessive bold[\s.!?]*$", m) ): return ControlAction("set_term_emphasis", "minimal") if len(m) <= 110 and re.match( r"^(please\s+)?(default emphasis|normal bold|reset emphasis)[\s.!?]*$", m, ): return ControlAction("set_term_emphasis", "normal") # Counterpoint tone: supportive vs challenge assumptions (short lines). if len(m) <= 110 and ( re.match(r"^(please\s+)?challenge my assumptions[\s.!?]*$", m) or re.match(r"^(please\s+)?play devils advocate[\s.!?]*$", m) or re.match(r"^(please\s+)?push back on weak points[\s.!?]*$", m) ): return ControlAction("set_counterpoint_tone", "challenge") if len(m) <= 110 and ( re.match(r"^(please\s+)?be supportive[\s.!?]*$", m) or re.match(r"^(please\s+)?assume good intent[\s.!?]*$", m) or re.match(r"^(please\s+)?encourage my ideas[\s.!?]*$", m) ): return ControlAction("set_counterpoint_tone", "supportive") if len(m) <= 110 and re.match( r"^(please\s+)?(default counterpoints|normal pushback|reset counterpoints)[\s.!?]*$", m, ): return ControlAction("set_counterpoint_tone", "normal") return None # Tokens for "write the reply in …" detection (allowlist avoids "in Python" / "in 24 hours"). _REPLY_LANG_TOKENS: dict[str, str] = { "arabic": "Arabic", "chinese": "Chinese (Simplified)", "czech": "Czech", "danish": "Danish", "dutch": "Dutch", "english": "English", "finnish": "Finnish", "french": "French", "german": "German", "greek": "Greek", "hebrew": "Hebrew", "hindi": "Hindi", "hungarian": "Hungarian", "indonesian": "Indonesian", "italian": "Italian", "japanese": "Japanese", "korean": "Korean", "norwegian": "Norwegian", "polish": "Polish", "portuguese": "Portuguese", "romanian": "Romanian", "russian": "Russian", "spanish": "Spanish", "swedish": "Swedish", "thai": "Thai", "turkish": "Turkish", "ukrainian": "Ukrainian", "vietnamese": "Vietnamese", } _LEN_CAP_UNIT_MAX: dict[str, int] = { "word": 2500, "words": 2500, "sentence": 80, "sentences": 80, "paragraph": 30, "paragraphs": 30, "line": 120, "lines": 120, } def _length_cap_instruction(m: str) -> tuple[str, str] | None: """If the user asked for a max length, return (system instruction, compact trace token).""" if len(m) < 24: return None patterns = [ re.compile( r"\b(?:in under|at most|no more than|under|within|no longer than)\s+(\d{1,4})\s+" r"(words?|sentences?|paragraphs?|lines?)\b" ), re.compile(r"\b(?:max|maximum)\s+(\d{1,4})\s+(words?|sentences?|paragraphs?|lines?)\b"), re.compile(r"\b(\d{1,4})\s+words?\s+(?:max|maximum|only|at most|or less)\b"), ] for rx in patterns: mo = rx.search(m) if not mo: continue n_raw, unit = mo.group(1), mo.group(2).lower() try: n = int(n_raw) except ValueError: continue cap = _LEN_CAP_UNIT_MAX.get(unit) if cap is None or n < 1 or n > cap: continue if unit.startswith("word"): plural, short = "words", "w" elif unit.startswith("sentence"): plural, short = "sentences", "s" elif unit.startswith("paragraph"): plural, short = "paragraphs", "p" else: plural, short = "lines", "ln" trace_tok = f"len_cap={n}{short}" instr = ( f"The user requested a **tight length cap** of about **{n} {plural}** for the full assistant answer " f"(including lists or headings). Stay at or under this cap; if it is impossible, say so in one short sentence " "then give the closest fit." ) return instr, trace_tok return None def _code_only_instruction(m: str) -> str | None: """Detect requests for code-heavy output with almost no prose.""" if len(m) < 18: return None if re.search( r"\b(just the code|(? tuple[str, str] | None: """``code_explained`` — snippet plus walkthrough (complement to ``code_only`` trace tag).""" if len(m) < 32: return None if not re.search( r"\b(code|script|function|snippet|program|implementation|bash|python|sql|regex|api|curl|" r"typescript|rust|java|module|class|method|algorithm)\b", m, ): return None explained = bool( re.search( r"\b(code (?:with|plus|and) (?:an? )?explanation|explain (?:the|what) (?:the )?code(?: does)?|" r"walk me through the (?:code|snippet)|comment(?:ed)? code|annotate (?:the )?(?:code|snippet)|" r"code (?:with|plus) (?:inline )?comments|don'?t (?:just )?give code without explaining|" r"not (?:just )?code only|no code[- ]only|" r"with (?:a )?line[- ]by[- ]line (?:walkthrough|explanation)|" r"explain (?:each|every) (?:line|part|step)|teach (?:me )?(?:through|with) the code|" r"show (?:me )?(?:the )?code (?:and|then) explain|" r"include (?:brief )?comments (?:in|on) the code)\b", m, ) ) if not explained: return None instr = ( "The user asked for **code with explanation**: include a **fenced code block** (or clearly separated snippet) " "**and** a concise walkthrough—what it does, non-obvious lines, and how to run or adapt it. " "Do **not** return code alone without prose." ) return instr, "code_explained" def _embedded_guided_discovery(m: str) -> tuple[str, str] | None: """``guided`` (hints-first) vs ``full_solution`` for problem-solving (not one-line controls).""" if len(m) < 36: return None if not re.search( r"\b(why|how|explain|prove|derive|solve|puzzle|homework|problem|exercise|bug|code|implement|" r"design|compare|understand|learn|teach|practice|algorithm|proof|debug|refactor)\b", m, ): return None guided = bool( re.search( r"\b(don'?t (give|spell|hand) (me )?(the )?full (answer|solution)|don'?t spoil the solution|" r"hints? only|only hints|guide me with (hints|questions)|nudge me (in the right direction|toward)|" r"i want to (figure|work) it out myself|socratic(\s+method)?|" r"lead me to (the )?answer|questions first instead of answering|" r"without (giving|spelling) (out )?(the )?(whole )?solution)\b", m, ) and not re.search(r"\bdon'?t do hints only\b", m) ) full = bool( re.search( r"\b(give me the (?:full|complete) (?:worked )?(?:answer|solution)|" r"(?:show|spell out) (?:me )?(?:the )?(?:full|entire|complete) (?:worked )?solution|" r"complete solution now|don'?t do hints only|no hints only|skip the socratic|" r"not hints only|" r"just (?:give|tell) me the answer|" r"finish the (?:proof|solution) for me|" r"i'?m stuck.{0,40}(?:full|complete) solution)\b", m, ) ) if guided and full: return None if guided: instr = ( "The user asked for **guided discovery** (Socratic / hint-first): prefer short **questions**, " "**nudges**, and **partial hints** over a complete solution in this turn. " "If one concrete step is essential, show **at most one** move, then check whether they want to continue. " "Offer the full worked answer if they say they are stuck or ask you to finish." ) return instr, "guided" if full: instr = ( "The user asked for a **complete solution** in this turn: provide the full worked answer with " "clear steps or reasoning—do **not** stay in hint-only or Socratic question mode unless a safety " "check is required." ) return instr, "full_solution" return None def _ephemeral_privacy_instruction(m: str) -> tuple[str, str] | None: """User asked not to treat this turn as content to persist (memory / logging).""" if len(m) < 22: return None if re.search( r"\b(off the record|no memory for this|nothing persisted|ephemeral question|ephemeral chat|" r"don'?t log this|don'?t persist this|" r"don'?t (?:remember|store) (?:this|that|it|anything)|" r"do not (?:remember|store) (?:this|that|it)|" r"please don'?t (?:remember|store) (?:this|that|it)|" r"forget this after|don'?t save (?:this|that)\s+to\s+memory)\b", m, ): instr = ( "The user signaled **ephemeral intent** for this reply: do **not** invite `/remember`, `/session`, or " "long-term note-taking for this content; avoid urging them to store secrets, API keys, or passwords. " "Still answer helpfully within normal safety and deployment limits." ) return instr, "ephemeral" return None def _accessibility_sr_instruction(m: str) -> tuple[str, str] | None: """User wants screen-reader / WCAG-minded answer structure (linear, semantic headings).""" if len(m) < 44: return None if not re.search( r"\b(screen[- ]?reader|screenreader|nvda|jaws|voiceover|talkback|orca|" r"wcag(?:\s+[0-9]{1,2}(?:\.[0-9])?)?|\ba11y\b|accessibility|accessible to|" r"blind users?|low vision|visually impaired)\b", m, ): return None audience = re.search( r"\bfor\s+(?:blind|low-vision|screen[- ]?reader|a11y)\s+(?:users?|readers?|audiences?|visitors?)?\b", m, ) format_rq = re.search( r"\b(friendly|friendlier|structure|structured|layout|linear|heading|headings|semantic|" r"readable|reformat|format this|annotate|describe (?:the\s+)?(?:chart|diagram|figure|image)|" r"please (?:reply|answer|write|help|summarize|reformat|structure)|" r"how (?:should|can) i (?:write|format|publish))\b", m, ) if not audience and not format_rq: return None instr = ( "The user asked for **screen-reader–friendly / accessibility-aware** formatting: prefer a **clear linear reading order**; " "use real markdown heading lines for sections when the answer is long; do **not** rely on a table as the **only** " "place critical facts appear—repeat key facts in prose if you use a table; briefly describe any chart or diagram " "in words; keep emoji sparse and never the sole carrier of meaning." ) return instr, "a11y" def _embedded_source_citations(m: str) -> tuple[str, str] | None: """``cite_sources`` vs ``cite_minimal`` — inline attribution for FAQ/web/supplied context.""" if len(m) < 44: return None if not re.search( r"\b(faq|policy|article|paper|report|study|news|web|search|source|reference|claim|fact|" r"research|documentation|docs|excerpt|snippet|evidence|retrieved|grounded)\b", m, ): return None sources = bool( re.search( r"\b(cite (?:your )?sources|include (?:source )?links|link to (?:your )?sources|" r"(?:give|provide) (?:inline )?citations|attribute (?:each )?(?:claim|point)|" r"reference(?:s)? for (?:each|every)|where (?:did|does) (?:this|that) come from|" r"back (?:each )?(?:claim|point) with (?:a )?(?:link|source)|" r"include (?:the )?urls|show (?:me )?(?:the )?sources you used|" r"audit[- ]ready (?:citations|references)|source attribution)\b", m, ) ) minimal = bool( re.search( r"\b(no (?:source )?links|don'?t cite(?: sources)?|skip (?:the )?links|" r"without links or citations|no bibliography|don'?t include urls|" r"no footnotes|answer without citing)\b", m, ) ) if sources and minimal: return None if sources: instr = ( "The user asked for **explicit source attribution**: when using FAQ excerpts, web snippets, " "or supplied context, **cite them inline** (e.g. `[FAQ excerpt 2]`, `[Web 1]`) and prefer " "**short links or clear source labels** for factual claims; say when something is general knowledge " "without a provided source." ) return instr, "cite_sources" if minimal: instr = ( "The user asked to **avoid heavy citation formatting**: answer in clear prose **without** " "a bibliography, long URL lists, or footnote blocks unless a single inline cite is essential " "for policy or safety." ) return instr, "cite_minimal" return None def _embedded_ranked_options(m: str) -> tuple[str, str] | None: """``ranked_options`` — user wants choices ordered by priority/merit, not flat peer lists.""" if len(m) < 48: return None if not re.search( r"\b(option|choice|alternative|approach|vendor|tool|framework|candidate|stack|" r"path|strategy|pick|recommend|solution|provider|platform|library|database|" r"architecture|design|method|technique|product)\b", m, ): return None ranked = bool( re.search( r"\b(rank (?:them|these|the|your)|ranked (?:list|recommendations?)|" r"in order of (?:priority|importance|preference|merit|likelihood)|" r"top \d+ (?:options?|choices?|picks?|recommendations?)|" r"ordered (?:from|by)|prioriti[sz]e (?:these|the|your)|" r"best to worst|strongest to weakest|from most to least|" r"highest to lowest(?: priority)?|" r"which (?:one|option) (?:first|should we pick first)|" r"order (?:them|these) by)\b", m, ) ) flat = bool( re.search( r"\b(no ranking|don'?t rank|order doesn'?t matter|unordered (?:list|options?)|" r"don'?t priorit[iy]ze|all options are equal|no priority order)\b", m, ) ) if ranked and flat: return None if ranked: instr = ( "The user asked for a **ranked recommendation**: present options in a **clear priority order** " "(best-first or explicitly numbered 1., 2., 3.) with a short rationale for the ordering; " "do not present every alternative as equally good when they asked for ranking." ) return instr, "ranked_options" return None def _embedded_checklist_reply(m: str) -> tuple[str, str] | None: """``checklist`` vs ``no_checklist`` — markdown ``- [ ]`` task layout (not bullet-only lists).""" if len(m) < 44: return None if not re.search( r"\b(rollout|deploy|launch|onboard|audit|review|procedure|task|step|plan|" r"migrate|implement|runbook|playbook|incident|release|checklist|todo|action item)\b", m, ): return None prefer = bool( re.search( r"\b((?:give|provide|format|return|list|use|write).{0,24}checklist|" r"as a checklist|checklist (?:format|style)|action[- ]items? checklist|" r"task checklist|tick[- ]box(?:es)?|checkbox(?:es)? (?:list|format)|" r"markdown checkbox|to[- ]do list format)\b", m, ) ) avoid = bool( re.search( r"\b(no checklist|not a checklist|don'?t use checkboxes|avoid checklist|" r"without checkboxes|not tick[- ]boxes)\b", m, ) ) if prefer and avoid: return None if prefer: instr = ( "The user asked for a **markdown checklist**: use **`- [ ]` task lines** (or `- [x]` if noting done) " "for actionable items; keep each item one short line; optional brief intro, then the checklist." ) return instr, "checklist" if avoid: instr = ( "The user asked **not** to format the answer as a markdown checkbox checklist; use prose, bullets, " "or numbered steps instead of `- [ ]` task lines." ) return instr, "no_checklist" return None def _embedded_pseudocode(m: str) -> tuple[str, str] | None: """``pseudocode`` vs ``runnable_code`` — abstract algorithm vs executable snippet.""" if len(m) < 36: return None if not re.search( r"\b(code|algorithm|function|script|program|logic|implementation|sort|search|" r"loop|recursion|data structure|complexity)\b", m, ): return None pseudo = bool( re.search( r"\b(pseudo[- ]code only|pseudocode only|pseudo code only|" r"language[- ]agnostic(?: algorithm)?|" r"don'?t need (?:real |working |runnable )?code|" r"abstract algorithm|plain[- ]english algorithm|" r"no syntax(?:-specific)? (?:code|details)|not runnable|non[- ]runnable)\b", m, ) ) runnable = bool( re.search( r"\b((? int | None: if tok.isdigit(): n = int(tok) return n if 1 <= n <= 10 else None return _OPTION_COUNT_WORDS.get(tok) def _embedded_fixed_option_count(m: str) -> tuple[str, str] | None: """``options_n=N`` — user wants exactly N distinct alternatives (not an open-ended list).""" if len(m) < 44: return None if not re.search( r"\b(options?|choices?|alternatives?|approaches?|ideas?|recommendations?|picks?|" r"paths?|solutions?|vendors?|tools?|frameworks?|strategies?|candidates?)\b", m, ): return None found: set[int] = set() for pat in _OPTION_COUNT_PATTERNS: for mo in pat.finditer(m): n = _parse_option_count_token(mo.group(1)) if n is not None: found.add(n) if len(found) != 1: return None n = next(iter(found)) instr = ( f"The user asked for **exactly {n} distinct options**: present **{n}** clearly labeled alternatives " f"(e.g. **Option 1** … **Option {n}**); do not pad with extras or collapse into fewer unless " f"{n} is infeasible—in that case say why in one short sentence." ) return instr, f"options_n={n}" def _embedded_diagram_visual(m: str) -> tuple[str, str] | None: """``diagram`` vs ``no_diagram`` — Mermaid/flowchart/ASCII visual vs text-only.""" if len(m) < 44: return None if not re.search( r"\b(architecture|system|flow|pipeline|process|workflow|diagram|chart|topology|" r"sequence|component|service|deploy|design|how|explain|model|map|overview|" r"interaction|request|data)\b", m, ): return None prefer = bool( re.search( r"\b(sequence diagram|architecture diagram|component diagram|system diagram|" r"flowchart|flow chart|" r"mermaid.{0,20}diagram|" r"(?:include|add|draw|show|provide|use|give me).{0,28}diagram|" r"(?:ascii|text[- ]based) diagram|" r"visual(?:ize| diagram)|" r"as a (?:mermaid )?flowchart)\b", m, ) ) avoid = bool( re.search( r"\b(no diagrams?|without diagrams?|don'?t (?:use|include) (?:a )?diagrams?|" r"avoid (?:mermaid|flowcharts?|diagrams?)|" r"text[- ]only (?:please|answer)|no (?:mermaid|flowcharts?)|" r"skip (?:the )?diagrams?|prose only no (?:charts?|diagrams?))\b", m, ) ) if prefer and avoid: return None if prefer: instr = ( "The user asked for a **visual diagram** in the reply: include **one** concise " "**Mermaid** diagram (preferred) or a short **ASCII** diagram when Mermaid is awkward; " "add brief prose before/after; keep node labels short." ) return instr, "diagram" if avoid: instr = ( "The user asked for **no diagrams**: answer in prose, bullets, numbered steps, or tables " "only—do **not** include Mermaid blocks, flowcharts, or ASCII art diagrams." ) return instr, "no_diagram" return None def _embedded_risks_benefits_order(m: str) -> tuple[str, str] | None: """``risks_first`` vs ``benefits_first`` — section order for trade-offs (not ``risk_posture``).""" if len(m) < 48: return None if not re.search( r"\b(plan|proposal|rollout|launch|migrate|design|strategy|decision|invest|build|ship|" r"product|feature|architecture|change|initiative|roadmap|pitch|trade[- ]?off)\b", m, ): return None risks = bool( re.search( r"\b(risks? first|downsides? first|cons first|what could go wrong first|" r"start with (?:the )?risks?|lead with (?:the )?risks?|" r"pitfalls? first|negative(?:s)? before positives?|" r"caveats? (?:before|then) benefits?|worst[- ]case first)\b", m, ) ) benefits = bool( re.search( r"\b(benefits? first|upsides? first|pros first|" r"start with (?:the )?benefits?|lead with (?:the )?upsides?|" r"positives? before negatives?|sell (?:me on )?the upside first|" r"good news first)\b", m, ) ) if risks and benefits: return None if risks: instr = ( "The user asked for **risks / downsides first**: open with key **risks, caveats, and failure modes** " "before benefits or recommendations; keep the ordering explicit even if you later add upsides." ) return instr, "risks_first" if benefits: instr = ( "The user asked for **benefits / upsides first**: open with **advantages and positive outcomes** " "before risks or caveats; keep the ordering explicit even if you note downsides later." ) return instr, "benefits_first" return None def _embedded_risks_mitigations(m: str) -> tuple[str, str] | None: """``risks_mitigations`` — paired risk + mitigation layout (not ``risks_first`` section order).""" if len(m) < 48: return None no_rm = bool( re.search( r"\b(no mitigations?|without mitigations?|skip (?:the\s+)?mitigation(?:s| plan)?|" r"don'?t (?:include|list) mitigations?|risks? only|" r"no (?:paired\s+)?mitigation section|avoid (?:a\s+)?mitigation section|" r"not a risk register|skip (?:the\s+)?risk register)\b", m, ) ) if no_rm: return None want = bool( re.search( r"\b(risks? and mitigations?|risks? with mitigations?|" r"mitigation(?:s| plan) for each risk|risk register|" r"list (?:the\s+)?(?:key\s+)?risks? (?:and|with) (?:corresponding\s+)?mitigations?|" r"each risk (?:with|and) (?:a\s+)?mitigation|" r"paired risk[- ]mitigation|mitigation steps? for (?:each|every) risk|" r"include mitigations? (?:for|against) (?:each|the) risks?)\b", m, ) ) if not want: return None if not re.search( r"\b(plan|proposal|rollout|launch|migrate|design|strategy|security|" r"compliance|initiative|project|deployment|change|review|assess|write|describe|outline|report)\b", m, ): return None instr = ( "The user wants a **risks + mitigations** layout: include a **Risks and mitigations** section " "where each key risk is paired with a **concrete mitigation** (bullets or a small table with " "Risk / Mitigation columns)—do not list risks without actionable mitigations." ) return instr, "risks_mitigations" def _embedded_revise_draft(m: str) -> tuple[str, str] | None: """``revise_draft`` — rewrite/polish user-supplied copy (not a greenfield explain-only ask).""" if len(m) < 48: return None revise = bool( re.search( r"\b(improve (?:my |this |the )?draft|polish (?:my |this |the )?(?:draft|email|memo)?|" r"rewrite (?:it|this|the (?:text|email|message))|" r"rewrite (?:my |this |the )?(?:draft|email|paragraph|message|memo|post|letter)|" r"edit (?:my |this )?(?:draft|text|copy)|proofread (?:my |this )?|" r"tighten (?:my |this )?(?:draft|writing|wording)|" r"make (?:this |it |the text )(?:clearer|more professional|more concise|shorter)|" r"copy[- ]?edit|wordsmithe)\b", m, ) ) no_revise = bool( re.search( r"\b(don'?t rewrite|do not rewrite|no rewrite|keep (?:my |the )?wording (?:as[- ]is|unchanged)|" r"don'?t edit (?:my |the )?text)\b", m, ) ) if not revise or no_revise: return None has_artifact = bool( re.search( r"\b(?:my|this|the)\s+draft\b|draft\s+(?:email|message|memo|slack|paragraph|letter|post)\b|" r"(?:text|email|memo)\s+below|following\s+(?:text|email|draft|memo)|" r"draft:\s|here(?:'s| is)\s+(?:my|the)\s+draft\b", m, ) ) if not has_artifact and len(m) < 100: return None instr = ( "The user wants a **revision of supplied text**: treat their message as source copy to " "**rewrite or polish in place**—preserve intent and facts; return the improved version prominently " "(add brief bullets on what changed only if helpful); do **not** answer as if no draft was provided." ) return instr, "revise_draft" def _embedded_revise_diff(m: str) -> tuple[str, str] | None: """``revise_diff`` — when revising supplied copy, show before/after or track-changes layout.""" if len(m) < 48: return None want_diff = bool( re.search( r"\b(before and after|before[- ]?after|side[- ]by[- ]side|" r"show (?:me )?(?:what|the) changed|show (?:the )?changes|track changes?|" r"redline(?:d)?(?:\s+version)?|diff format|as a diff|" r"strikethrough (?:for|on) (?:removed|deletions)|" r"highlight (?:what|the) changed|compare (?:the )?original (?:to|with|and))\b", m, ) ) no_diff = bool( re.search( r"\b(no before and after|don'?t show (?:a )?diff|without (?:a )?diff|" r"no track changes?|inline revision only|revision only no diff|" r"don'?t (?:show|include) (?:before|after)|skip (?:the )?diff)\b", m, ) ) if not want_diff or no_diff: return None revise = bool( re.search( r"\b(improve (?:my |this |the )?draft|polish|rewrite|edit (?:my |this )?|" r"proofread|copy[- ]?edit|revise (?:my |this |the )?|tighten (?:my )?)\b", m, ) ) has_artifact = bool( re.search( r"\b(?:my|this|the)\s+draft\b|draft\s+(?:email|message|memo|slack|paragraph|letter|post)\b|" r"(?:text|email|memo)\s+below|following\s+(?:text|email|draft|memo)|" r"draft:\s|here(?:'s| is)\s+(?:my|the)\s+draft\b", m, ) ) if not revise and not has_artifact: return None if not has_artifact and len(m) < 96: return None instr = ( "The user wants a **before/after or track-changes style revision**: label sections **Before** " "and **After** (or use a concise unified diff / `~~removed~~` / **added** markup for changed spans). " "Keep the polished **After** copy complete; do not answer as if no source draft was provided." ) return instr, "revise_diff" def _embedded_email_format(m: str) -> tuple[str, str] | None: """``email_format`` — Subject / Greeting / Body / Sign-off layout (greenfield compose, not polish).""" if len(m) < 48: return None no_ef = bool( re.search( r"\b(no email format|without (?:an?\s+)?email format|not an email format|" r"skip (?:the\s+)?email format|don'?t use email format|" r"avoid email format|not as an email|no subject line block)\b", m, ) ) if no_ef: return None revise_only = bool( re.search( r"\b(rewrite (?:my |this |the )?(?:draft )?|polish (?:my |this )?(?:draft )?|" r"proofread (?:my |this )?|improve (?:my |this |the )?draft|copy[- ]?edit)\b", m, ) ) has_draft_artifact = bool( re.search( r"\b(?:my|this|the)\s+draft\b|draft:\s|here(?:'s| is)\s+(?:my|the)\s+draft\b", m, ) ) if revise_only and has_draft_artifact: return None want = bool( re.search( r"\b((?:write|draft|compose|prepare) (?:an?\s+)?email|" r"email (?:to|for) (?:the |my |our |a )?|" r"email format|as an email|in email format|" r"follow[- ]up email|outreach email|" r"reply (?:by|as|in) email|email (?:message|template))\b", m, ) ) if not want: return None if not re.search( r"\b(write|draft|compose|prepare|notify|inform|send|follow[- ]?up|" r"apolog|request|update|client|customer|colleague|manager|team|" r"recipient|message|explain|describe)\b", m, ): return None instr = ( "The user wants a **formatted email**: use labels **Subject:** (one line), " "a **Greeting** (Hi/Dear …), concise body paragraphs, and a **Sign-off** " "(Thanks/Best regards + optional name/role)—ready to paste into an email client; " "do not answer as a generic essay about how to write emails." ) return instr, "email_format" def _embedded_letter_format(m: str) -> tuple[str, str] | None: """``letter_format`` — formal business letter layout (distinct from ``email_format``).""" if len(m) < 48: return None no_lf = bool( re.search( r"\b(no letter format|without (?:a\s+)?letter format|not a letter format|" r"skip (?:the\s+)?letter format|don'?t use letter format|" r"avoid letter format|not as a letter|no formal letter (?:format|layout))\b", m, ) ) if no_lf: return None revise_only = bool( re.search( r"\b(rewrite (?:my |this |the )?(?:draft )?|polish (?:my |this )?(?:draft )?|" r"proofread (?:my |this )?|improve (?:my |this |the )?draft|copy[- ]?edit)\b", m, ) ) has_draft_artifact = bool( re.search( r"\b(?:my|this|the)\s+draft\b|draft:\s|here(?:'s| is)\s+(?:my|the)\s+draft\b", m, ) ) if revise_only and has_draft_artifact: return None email_only = bool( re.search( r"\b((?:write|draft|compose|prepare) (?:an?\s+)?email|" r"email format|as an email|in email format|follow[- ]up email)\b", m, ) ) if email_only: return None want = bool( re.search( r"\b((?:write|draft|compose|prepare) (?:a\s+)?(?:formal\s+)?letter|" r"letter (?:to|for) (?:the |my |our |a )?|" r"letter format|formal letter(?:\s+format)?|business letter(?:\s+format)?|" r"as a letter|in letter format|cover letter format|" r"official letter|letter of (?:request|notice|complaint|support))\b", m, ) ) if not want: return None if not re.search( r"\b(write|draft|compose|prepare|notify|inform|send|request|apolog|" r"client|customer|office|agency|regulator|recipient|legal|" r"describe|explain|mail|correspondence)\b", m, ): return None instr = ( "The user wants a **formal letter**: use labels **Date:**, **To:** (recipient name/address), " "**Salutation** (Dear …), body paragraphs, **Closing** (Sincerely / Respectfully), and " "**Signature** (name + title)—ready to print or mail; not an email with Subject/Greeting blocks." ) return instr, "letter_format" def _embedded_press_release(m: str) -> tuple[str, str] | None: """``press_release`` — media/PR announcement layout (distinct from ``email_format`` and ``letter_format``).""" if len(m) < 48: return None no_pr = bool( re.search( r"\b(no press release|without (?:a\s+)?press release|not a press release|" r"skip (?:the\s+)?press release|don'?t use press release|" r"avoid press release (?:format|template|layout)|" r"no press release format|skip (?:the\s+)?press release format|" r"not as a press release)\b", m, ) ) if no_pr: return None revise_only = bool( re.search( r"\b(rewrite (?:my |this |the )?(?:draft )?|polish (?:my |this )?(?:draft )?|" r"proofread (?:my |this )?|improve (?:my |this |the )?draft|copy[- ]?edit)\b", m, ) ) has_draft_artifact = bool( re.search( r"\b(?:my|this|the)\s+draft\b|draft:\s|here(?:'s| is)\s+(?:my|the)\s+draft\b", m, ) ) if revise_only and has_draft_artifact: return None email_only = bool( re.search( r"\b((?:write|draft|compose|prepare) (?:an?\s+)?email|" r"email format|as an email|in email format|follow[- ]up email)\b", m, ) ) if email_only: return None letter_only = bool( re.search( r"\b(letter format|formal letter(?:\s+format)?|business letter(?:\s+format)?|" r"(?:write|draft) (?:a\s+)?(?:formal\s+)?letter to)\b", m, ) ) if letter_only: return None want = bool( re.search( r"\b(press release(?:\s+format)?|media release(?:\s+format)?|" r"news release(?:\s+format)?|pr announcement(?:\s+format)?|" r"write (?:a\s+)?press release|draft (?:a\s+)?press release|" r"compose (?:a\s+)?press release|prepare (?:a\s+)?press release|" r"press release (?:for|about|announcing)|" r"media announcement(?:\s+format)?)\b", m, ) ) if not want: return None if not re.search( r"\b(announce|launch|product|company|startup|partnership|milestone|" r"media|journalist|reporter|pr\b|communications|comms|" r"write|draft|compose|prepare|publish|describe|outline)\b", m, ): return None instr = ( "The user wants a **press release**: use markdown headings **FOR IMMEDIATE RELEASE**, " "**Headline**, optional **Subhead**, **Dateline** (City, Date —), a **Lead paragraph** " "(who/what/when/where/why), **Body** (details + optional executive quote), " "**About [Company]** boilerplate, and **Media contact**—journalist-ready copy; " "not an email with Subject/Greeting or a formal business letter with To/Salutation blocks." ) return instr, "press_release" def _embedded_runbook_format(m: str) -> tuple[str, str] | None: """``runbook_format`` — ops/on-call runbook scaffold (distinct from ``postmortem`` and ``checklist``).""" if len(m) < 48: return None no_rb = bool( re.search( r"\b(no runbook format|without (?:a\s+)?runbook format|not a runbook format|" r"skip (?:the\s+)?runbook format|don'?t use runbook format|" r"avoid runbook (?:format|template|sections)|" r"no operational runbook (?:format|template))\b", m, ) ) if no_rb: return None checklist_only = bool( re.search( r"\b((?:as a|use a|markdown) checklist|checklist (?:format|style)|" r"tick[- ]box(?:es)?|checkbox(?:es)? (?:list|format))\b", m, ) ) if checklist_only: return None postmortem_only = bool( re.search( r"\b(postmortem format|blameless postmortem|incident postmortem|" r"post[- ]mortem format)\b", m, ) ) if postmortem_only: return None want = bool( re.search( r"\b(runbook(?:\s+format)?|operational runbook|on[- ]call runbook|" r"incident runbook|ops runbook|" r"write (?:an?\s+)?runbook|draft (?:an?\s+)?runbook|" r"playbook format|operational playbook|" r"runbook (?:for|to) (?:the\s+)?(?:on[- ]call|failover|rollback|restore|deploy))\b", m, ) ) if not want: return None if not re.search( r"\b(on[- ]call|incident|outage|failover|rollback|restore|deploy|" r"sre|operations|ops|escalat|drill|procedure|write|draft|" r"describe|outline|publish|document)\b", m, ): return None instr = ( "The user wants an **operational runbook**: use markdown headings **Purpose**, " "**Prerequisites**, **Procedure** (numbered steps), **Verification**, **Rollback**, " "**Escalation**, and optional **References**—concrete operator actions, not a " "postmortem narrative or `- [ ]` checkbox checklist." ) return instr, "runbook_format" def _embedded_job_aid(m: str) -> tuple[str, str] | None: """``job_aid`` — quick-reference / performance-support card (distinct from ``runbook_format`` and ``checklist``).""" if len(m) < 48: return None no_ja = bool( re.search( r"\b(no job aid|without (?:a\s+)?job aid|not a job aid|" r"skip (?:the\s+)?job aid|don'?t use job aid|" r"avoid job aid (?:format|template|sections)|" r"no job aid format|skip (?:the\s+)?job aid format)\b", m, ) ) if no_ja: return None runbook_only = bool( re.search( r"\b(runbook(?:\s+format)?|operational runbook|on[- ]call runbook|" r"incident runbook|ops runbook|operational playbook)\b", m, ) ) if runbook_only: return None checklist_only = bool( re.search( r"\b((?:as a|use a|markdown) checklist|checklist (?:format|style)|" r"tick[- ]box(?:es)?|checkbox(?:es)? (?:list|format))\b", m, ) ) if checklist_only: return None want = bool( re.search( r"\b(job aid(?:\s+format)?|job[- ]aid (?:card|template|format)|" r"quick reference(?:\s+card|\s+guide|\s+format)?|" r"cheat sheet(?:\s+format)?|desk reference|" r"performance support(?:\s+tool|\s+format)?|" r"write (?:a\s+)?job aid|draft (?:a\s+)?job aid|" r"quick[- ]reference (?:for|on))\b", m, ) ) if not want: return None if not re.search( r"\b(training|onboarding|frontline|agent|staff|employee|team|" r"task|workflow|process|procedure|support|help desk|" r"write|draft|create|outline|document|describe|publish)\b", m, ): return None instr = ( "The user wants a **job aid** (quick-reference card): use markdown headings **Task / purpose**, " "**When to use**, **Quick steps** (numbered, scannable), **Tips & reminders**, " "**Common mistakes**, and **Need help?**—compact performance support for someone doing " "the task at work; not an ops runbook with rollback/escalation or a `- [ ]` checkbox checklist." ) return instr, "job_aid" def _embedded_status_report(m: str) -> tuple[str, str] | None: """``status_report`` — periodic project/program status update (distinct from ``one_pager``).""" if len(m) < 48: return None no_sr = bool( re.search( r"\b(no status report|without (?:a\s+)?status report|not a status report|" r"skip (?:the\s+)?status report|don'?t use status report|" r"avoid status report (?:format|sections)|" r"no status report format|skip (?:the\s+)?status report format)\b", m, ) ) if no_sr: return None one_pager_only = bool( re.search( r"\b(one[- ]pager(?:\s+format|\s+memo|\s+brief)?|" r"single[- ]page (?:brief|memo|summary)|executive one[- ]pager)\b", m, ) ) if one_pager_only: return None want = bool( re.search( r"\b(status report(?:\s+format)?|project status report|program status report|" r"weekly status (?:report|update)|monthly status (?:report|update)|" r"status update (?:format|for)|" r"rag status (?:report|update)|red[- ]amber[- ]green status|" r"write (?:a\s+)?status (?:report|update)|draft (?:a\s+)?status (?:report|update))\b", m, ) ) if not want: return None if not re.search( r"\b(project|program|initiative|migration|rollout|delivery|milestone|" r"sprint|stakeholder|leadership|pmo|update|report|outline|write|draft|describe)\b", m, ): return None instr = ( "The user wants a **status report**: use markdown headings **Reporting period**, " "**Overall status** (Green/Amber/Red or On track/At risk/Blocked), **Highlights**, " "**Blockers / lowlights**, optional **Key metrics**, **Next period focus**, and " "**Risks / asks**—scannable for stakeholders; not a one-pager executive memo." ) return instr, "status_report" def _embedded_meeting_agenda(m: str) -> tuple[str, str] | None: """``meeting_agenda`` — timeboxed meeting run-of-show (distinct from ``action_plan`` owner tables).""" if len(m) < 48: return None no_ma = bool( re.search( r"\b(no meeting agenda|without (?:a\s+)?meeting agenda|not a meeting agenda|" r"skip (?:the\s+)?meeting agenda|don'?t use meeting agenda|" r"avoid meeting agenda (?:format|section)|" r"no agenda format|skip (?:the\s+)?agenda format)\b", m, ) ) if no_ma: return None want = bool( re.search( r"\b(meeting agenda(?:\s+format)?|agenda format|" r"prepare (?:an?\s+)?agenda|draft (?:an?\s+)?agenda|" r"run[- ]of[- ]show|meeting run[- ]of[- ]show|" r"timeboxed agenda|agenda with time(?:\s+)?boxes?|" r"agenda for (?:the |our |a )?(?:meeting|sync|workshop|kickoff|review))\b", m, ) ) if not want: return None if not re.search( r"\b(meeting|sync|workshop|kickoff|review|standup|retro|planning|" r"session|facilitate|host|schedule|attendees|discuss|outline|write|prepare)\b", m, ): return None instr = ( "The user wants a **meeting agenda**: use markdown headings **Meeting title**, " "**Objective** (1–2 lines), optional **Attendees**, **Agenda** as timeboxed items " "(e.g. `5 min — Topic`), **Pre-reads / prep** if relevant, and **Decisions needed**—" "keep it scannable for a live facilitator; not a checkbox checklist or owner/due-date table." ) return instr, "meeting_agenda" def _embedded_topic_guard(m: str) -> tuple[str, str] | None: """``topic_guard`` — user asked to omit specific subjects from the reply.""" if len(m) < 44: return None avoid = bool( re.search( r"\b(don'?t mention|do not mention|avoid (?:mentioning|discussing|talking about)|" r"skip (?:mentioning|discussing)|leave out|no discussion of|" r"do not discuss|steer clear of|without mentioning|" r"don'?t bring up|do not bring up|exclude (?:any )?discussion of)\b", m, ) ) must_cover = bool( re.search( r"\b(make sure to mention|be sure to (?:mention|cover)|must (?:mention|cover|discuss)|" r"you must (?:mention|cover)|focus (?:only )?on|only discuss|" r"include (?:a )?section on)\b", m, ) ) if not avoid or must_cover: return None if not re.search( r"\b(explain|describe|what|how|why|help|write|draft|answer|summarize|compare|" r"faq|policy|guide|customer|user|team|product)\b", m, ): return None instr = ( "The user set **topic guardrails**: do **not** mention or elaborate on subjects they flagged to " "avoid in this message (for example pricing, competitors, politics, or internal tools)—even if " "tangentially relevant; you may note briefly that you are omitting a flagged topic." ) return instr, "topic_guard" def _embedded_topic_must(m: str) -> tuple[str, str] | None: """``topic_must`` — user required specific subjects or sections in the reply.""" if len(m) < 44: return None must_cover = bool( re.search( r"\b(make sure to mention|be sure to (?:mention|cover)|must (?:mention|cover|discuss|include)|" r"you must (?:mention|cover)|need (?:you )?to (?:mention|cover)|" r"include (?:a )?(?:section|subsection) (?:on|about|for)|" r"dedicated section (?:on|about|for)|don'?t skip (?:mentioning|discussing)|" r"address (?:the )?(?:topic|question) of|cover (?:the )?topic of)\b", m, ) ) avoid = bool( re.search( r"\b(don'?t mention|do not mention|avoid (?:mentioning|discussing|talking about)|" r"skip (?:mentioning|discussing)|leave out|no discussion of|" r"do not discuss|steer clear of|without mentioning|" r"don'?t bring up|do not bring up|exclude (?:any )?discussion of)\b", m, ) ) if not must_cover or avoid: return None if not re.search( r"\b(explain|describe|what|how|why|help|write|draft|answer|summarize|compare|" r"faq|policy|guide|customer|user|team|product|outline|prepare)\b", m, ): return None instr = ( "The user set **required topics**: explicitly **cover** each subject or section they asked " "you to mention (use clear headings or bullets per required item); do not omit flagged " "must-cover topics even if they seem tangential." ) return instr, "topic_must" def _embedded_answer_frame(m: str) -> tuple[str, str] | None: """``frame_star`` / ``frame_prep`` / ``frame_irac`` — named professional answer scaffolds.""" if len(m) < 48: return None if not re.search( r"\b(answer|write|explain|describe|respond|interview|behavioral|prompt|story|" r"example|scenario|case|memo|report|outline)\b", m, ): return None candidates: list[tuple[str, str]] = [] if re.search( r"\b(star format|star method|situation[- ]task[- ]action[- ]result|" r"\bstar\b.{0,30}(?:situation|task|action|result))\b", m, ): candidates.append( ( "Structure the answer using **STAR** with markdown headings **Situation**, **Task**, " "**Action**, and **Result** (one short paragraph each unless a length cap applies).", "frame_star", ) ) if re.search(r"\b(prep format|prep method|point[- ]reason[- ]example[- ]point)\b", m): candidates.append( ( "Structure the answer using **PREP**: **Point**, **Reason**, **Example**, then restate the **Point**.", "frame_prep", ) ) if re.search(r"\b(irac format|irac method|issue[- ]rule[- ]analysis[- ]conclusion)\b", m): candidates.append( ( "Structure the answer using **IRAC**: **Issue**, **Rule**, **Analysis**, **Conclusion**.", "frame_irac", ) ) if len(candidates) != 1: return None return candidates[0] def _embedded_simple_audience(m: str) -> bool: """True if a longer prompt asks for child-level / lay explanations (ELI5-style) in prose.""" if len(m) < 40: return False if re.search( r"\b(expert mode|technical audience|assume i'?m technical|phd level|for experts|deep technical)\b", m, ): return False if not re.search( r"\b(eli5|explain like i'?m(?:\s+a)? five|like i'?m(?:\s+a)? five\b|" r"for (?:my )?kids to understand|total beginner|i'?m\s+a\s+beginner\b|beginner\s+here\b|" r"non-technical (?:parent|reader|manager|audience)|" r"lay audience|no technical background|zero prior knowledge)\b", m, ): return False return bool( re.search( r"\b(why|how|what|when|where|explain|describe|tell me|help me (?:to )?understand|walk me through|" r"learn about|new to)\b", m, ) ) def _embedded_technical_audience(m: str) -> bool: """True if a longer prompt asks for expert-depth explanations (not short *Expert mode* controls).""" if len(m) < 40: return False if re.search( r"\b(eli5|explain like i'?m(?:\s+a)? five|total beginner|i'?m\s+a\s+beginner\b|beginner\s+here\b|" r"lay audience|no technical background|zero prior knowledge|explain simply)\b", m, ): return False if not re.search( r"\b(expert mode|technical audience|assume i'?m technical|phd level|for experts|deep technical|" r"staff engineer audience|senior (?:sre|eng|engineer) audience|" r"use jargon freely|skip the basics|don'?t dumb (?:it )?down|" r"peer[- ]level technical|internals[- ]focused|implementation[- ]heavy)\b", m, ): return False return bool( re.search( r"\b(why|how|what|when|where|explain|describe|tell me|walk me through|" r"compare|design|architect|debug|troubleshoot|analyze|review|implement)\b", m, ) ) def _embedded_register_tone(m: str) -> str | None: """One-shot formal vs casual register when prose names an audience (not the short *Formal tone* control).""" if len(m) < 48: return None formal = re.search( r"\b(board-ready|for regulators|regulatory filing|formal memo|audit[- ]friendly|" r"client-facing|for (?:the\s+)?board(?:\s+of\s+directors)?\b|for leadership review|" r"executive summary for|c[- ]suite|for executives|board presentation|investor[- ]ready|" r"sec filing tone)\b", m, ) casual = re.search( r"\b(slack message|teams message to the team|keep it casual|casual tone|friendly teammate|" r"like you(?:'re|\s+are)\s+my coworker|water cooler|informal note|keep it light|" r"pub chat|chatty tone)\b", m, ) if formal and not casual: return "formal" if casual and not formal: return "casual" return None def _embedded_verbosity(m: str) -> str | None: """``brief`` vs ``detailed`` reply length (not short *Be brief* controls; distinct from ``len_cap``).""" if len(m) < 44: return None detailed = bool( re.search( r"\b(more detail|go deeper|in greater detail|explain thoroughly|longer answers?|" r"detailed answers?|comprehensive explanation|deep dive|" r"don'?t skimp on detail|fuller explanation|elaborate (?:on|please)|" r"walk me through (?:it )?in depth)\b", m, ) ) brief = bool( re.search( r"\b(be brief|stay brief|keep it short|short answers?|answer briefly|concise replies?|" r"keep (?:your )?answer short|just the essentials|high[- ]level summary only|" r"don'?t ramble|brevity (?:please|is key))\b", m, ) ) if brief and detailed: return None if brief: return "brief" if detailed: return "detailed" return None def _embedded_output_format(m: str) -> str | None: """``json`` vs ``plain`` output shape (not short *Answer in JSON* / *Plain text only* controls).""" if len(m) < 40: return None plain = bool( re.search( r"\b(plain text only|no json(?:\s+block)?|not json|avoid json|skip json|" r"no structured output|don'?t use json|without json|" r"normal (?:plain )?text(?:\s+only)?|prose only.{0,30}no json|" r"don'?t (?:return|emit|output) json)\b", m, ) ) json_fmt = bool( re.search( r"\b(valid json|return json|reply in json|answer in json|json output|structured json|" r"json object|json array|as json\b|as a json|machine[- ]readable json|emit json|" r"serialize (?:to|as) json|output as json|respond with json)\b", m, ) ) if plain and json_fmt: return None if plain: return "plain" if json_fmt: return "json" return None def _embedded_speculation(m: str) -> str | None: """``strict`` vs ``creative`` speculation level (not short *No speculation* / *Brainstorm freely* controls).""" if len(m) < 44: return None creative = bool( re.search( r"\b(brainstorm freely|speculate freely|wild ideas(?:\s+ok)?|creative speculation|" r"go ahead and guess|reasonable guesses welcome|speculate a bit|" r"blue[- ]sky (?:thinking|ideas)|throw out (?:some )?possibilities|" r"explore hypotheticals|what[- ]if scenarios (?:are )?welcome|" r"ideation (?:mode|session)|open[- ]ended brainstorming)\b", m, ) ) strict = bool( re.search( r"\b(don'?t guess|no guessing|avoid guessing|only high confidence|stick to (?:the\s+)?facts|" r"avoid halluc|no hallucinations|don'?t hallucinate|if you don'?t know say|" r"if unsure say|say when you(?:'re|\s+are)\s+unsure|no speculation|avoid speculation|" r"don'?t speculate|fact[- ]checked|grounded only|evidence[- ]based only|" r"only if (?:you(?:'re|\s+are)\s+)?(?:certain|sure)|do not invent (?:facts|numbers))\b", m, ) ) if creative and strict: return None if strict: return "strict" if creative: return "creative" return None def _embedded_answer_lead(m: str) -> str | None: """``tldr_first`` vs ``direct`` answer opening (not short *TLDR first* / *Answer directly* controls).""" if len(m) < 44: return None direct = bool( re.search( r"\b(no tldr|skip (?:the )?summary|answer directly|without a (?:summary|tldr)|" r"no executive summary|don'?t (?:add|give) a tldr|direct answer only|" r"jump straight to the answer|no summary (?:upfront|at the top)|" r"get straight to the (?:answer|point)|omit (?:the )?(?:opening )?summary)\b", m, ) ) tldr = bool( re.search( r"\b(tl;?dr first|tldr first|lead with (?:a\s+)?(?:one[- ]line\s+)?summary|summary first|" r"executive summary first|bottom line up front|bluf|" r"start with (?:a\s+)?(?:short\s+)?summary|headline first|" r"give me the (?:key\s+)?takeaway first)\b", m, ) ) if direct and tldr: return None if direct: return "direct" if tldr: return "tldr_first" return None def _embedded_recommendation_first(m: str) -> tuple[str, str] | None: """``recommendation_first`` — open with an explicit recommendation before rationale (not generic BLUF).""" if len(m) < 44: return None no_rec = bool( re.search( r"\b(no recommendation (?:upfront|first|at the top)|" r"don'?t (?:lead with|start with|give) (?:your\s+)?recommendation|" r"skip (?:the\s+)?(?:upfront\s+)?recommendation|" r"without (?:an?\s+)?(?:upfront\s+)?recommendation|" r"recommendation (?:only\s+)?at the end|" r"conclude with (?:your\s+)?recommendation|" r"end with (?:your\s+)?recommendation|" r"hold (?:your\s+)?recommendation until (?:the\s+)?end)\b", m, ) ) if no_rec: return None want = bool( re.search( r"\b(lead with (?:your\s+)?recommendation|recommendation first|" r"state your recommendation (?:upfront|first|at the top)|" r"start with (?:your\s+)?(?:clear\s+)?recommendation|" r"give (?:your\s+)?recommendation (?:upfront|first|at the top)|" r"upfront recommendation (?:then|before)|" r"recommendation before (?:the\s+)?(?:analysis|rationale|details)|" r"open with (?:your\s+)?recommendation|" r"lead with what you recommend)\b", m, ) ) if not want: return None if not re.search( r"\b(recommend|choose|pick|select|decide|advise|should we|which (?:option|approach|tool|vendor)|" r"go with|prefer|adoption|migrate|switch|buy|build vs buy)\b", m, ): return None instr = ( "The user wants **recommendation-first** structure: open with a short **Recommendation** line " "that states clearly what you advise (one concrete choice or go/no-go), **then** provide " "supporting rationale—do not bury the recommendation after long background." ) return instr, "recommendation_first" def _embedded_go_no_go(m: str) -> tuple[str, str] | None: """``go_no_go`` — explicit Go / No-go / Conditional gate verdict for approval reviews.""" if len(m) < 48: return None no_gng = bool( re.search( r"\b(no go[- ]?/?no[- ]?go|without (?:a\s+)?go[- ]?/?no[- ]?go|" r"skip (?:the\s+)?go[- ]?/?no[- ]?go|not a go[- ]?/?no[- ]?go|" r"don'?t (?:include|use) go[- ]?/?no[- ]?go|" r"avoid go[- ]?/?no[- ]?go (?:format|section|verdict)|" r"no proceed[- ]or[- ]halt section)\b", m, ) ) if no_gng: return None want = bool( re.search( r"\b(go[- ]?/?no[- ]?go (?:decision|recommendation|verdict|call|assessment)|" r"go or no[- ]go|no[- ]go or go|" r"proceed or (?:halt|pause|stop)|halt or proceed|" r"should we proceed (?:or|vs\.?) (?:pause|halt|stop|wait)|" r"gate review (?:decision|memo|recommendation)|" r"approval gate (?:decision|review)|" r"launch gate (?:decision|review)|" r"explicit (?:go|no[- ]go) (?:verdict|recommendation))\b", m, ) ) if not want: return None if not re.search( r"\b(rollout|launch|release|migrate|deploy|production|project|initiative|" r"approve|approval|steering|committee|board|gate|proceed|write|memo|report|assess|decide)\b", m, ): return None instr = ( "The user wants a **go/no-go gate** verdict: open with a bold **Go**, **No-go**, or " "**Conditional go** line (pick one), then brief **Criteria met**, **Risks / blockers**, and " "**Conditions** (if conditional)—keep it decision-ready for an approval meeting." ) return instr, "go_no_go" def _embedded_actionability(m: str) -> str | None: """``commands`` vs ``conceptual`` actionability (not short *Make it actionable* / *Conceptual only* controls).""" if len(m) < 44: return None conceptual = bool( re.search( r"\b(conceptual only|high level only|no commands|without commands|no shell commands|" r"avoid command dumps|don'?t include (?:bash|shell|terminal) commands|" r"focus on concepts(?:\s+and\s+rationale)?|strategic discussion only|" r"architecture overview only|no runnable snippets|theory and tradeoffs only)\b", m, ) ) commands = bool( re.search( r"\b(include (?:a\s+)?(?:bash|sh|zsh|powershell) snippet|run(?:nable)? commands?|" r"copy[- ]paste (?:into )?(?:the\s+)?(?:terminal|shell)|" r"curl (?:one[- ]?liner|example)|one[- ]liner (?:for|to)|" r"bash one[- ]liner|powershell command|terminal commands?|" r"give me (?:the\s+)?(?:exact\s+)?commands?|include kubectl|" r"docker (?:run|compose) (?:example|snippet)|(?:pip|npm|pnpm|yarn) install (?:line|command)|" r"ready[- ]to[- ]run (?:script|snippet)|paste(?:able)? commands?)\b", m, ) ) if conceptual and commands: return None if conceptual: return "conceptual" if commands: return "commands" return None def _embedded_confidence_tone(m: str) -> str | None: """``transparent`` vs ``assertive`` confidence (not short *Flag assumptions* / *Be decisive* controls).""" if len(m) < 44: return None skip_transparent = bool( re.search( r"\b(no assumptions? section|skip (?:the\s+)?assumptions?|don'?t list assumptions|" r"without caveats|no caveats|omit limitations)\b", m, ) ) transparent = ( not skip_transparent and ( bool( re.search( r"\b(state|list|spell out|call out|identify|enumerate|label)\s+" r"(?:your\s+|the\s+|our\s+|key\s+|main\s+)?(?:key\s+|main\s+)?assumptions?\b", m, ) ) or bool( re.search( r"\b(assumptions?\s+and\s+limitations?|limitations?\s+and\s+caveats?|" r"limitations?\s+section|caveats?\s+(?:first|upfront|at\s+the\s+top)|" r"upfront\s+caveats?|scope\s+and\s+assumptions?|boundary\s+conditions?|" r"what\s+(?:we\s+)?(?:are\s+)?assuming\b|" r"explicit(?:ly)?\s+about\s+(?:limitations?|uncertainty|what\s+we\s+don'?t\s+know)|" r"where\s+this\s+(?:breaks?\s+down|stops?\s+working|doesn'?t\s+apply))\b", m, ) ) or bool( re.search( r"\b(flag|surface|highlight)\s+(?:key\s+)?(?:uncertainties|unknowns|gaps|risk\s+factors)\b", m, ) ) ) ) assertive = bool( re.search( r"\b(be decisive|don'?t hedge|give firm answers?|minimal hedging|" r"sound\s+confident|avoid disclaimers|confident (?:recommendation|tone)|" r"take a clear stance|no throat[- ]clearing|decisive recommendation)\b", m, ) ) if transparent and assertive: return None if transparent: return "transparent" if assertive: return "assertive" return None def _embedded_example_density(m: str) -> str | None: """``rich`` or ``sparse`` from prose (not the short *Include examples* / *Skip examples* control lines).""" if len(m) < 44: return None sparse = bool( re.search( r"\b(skip examples?|don'?t add examples?|don'?t include examples?|" r"without examples?|keep (?:it\s+)?abstract|theory[- ]only|abstract only|" r"example[- ]free|no examples? (?:please|in your (?:answer|reply))|" r"avoid illustrative examples?)\b", m, ) ) rich = bool( re.search( r"\b(include (?:at\s+least\s+)?(?:one|two|a few)\s+concrete examples?|" r"at least one (?:short\s+)?concrete example|" r"illustrate (?:this|that|it)\s+with (?:a\s+)?(?:concrete\s+|real[- ]world\s+)?example|" r"worked example|walk(?:\s+me)? through (?:a\s+)?(?:small|tiny|toy|minimal)\s+example|" r"\b(?:a\s+)?toy example\b|miniature scenario|" r"ground (?:this|it|your answer) in (?:a\s+)?(?:concrete\s+)?example|" r"give (?:me\s+)?a (?:concrete\s+)?example|" r"show (?:me\s+)?(?:this\s+)?with (?:a\s+)?(?:concrete\s+)?example)\b", m, ) ) if sparse and rich: return None if sparse: return "sparse" if rich: return "rich" return None def _embedded_exposition_order(m: str) -> str | None: """``definitions_first`` vs ``intuition_first`` from prose (not short *Definitions first* controls).""" if len(m) < 48: return None if re.search( r"\b(skip definitions first|don'?t start with definitions|" r"no formal definitions upfront)\b", m, ): return None if re.search( r"\b(skip the intuition|cut the warm[- ]?up|no hand[- ]?wavy intro)\b", m, ): return None defn = bool( re.search( r"\b(define (?:the\s+)?(?:key\s+)?terms? (?:first|before|upfront)|" r"definitions?\s+(?:first|before|upfront)|" r"start with (?:a\s+)?(?:brief\s+)?definition|" r"formal definitions? (?:first|before)|" r"precise definitions? before|" r"terminology (?:first|upfront)|" r"establish definitions before|" r"glossary[- ]style (?:intro|opening)|" r"define jargon before)\b", m, ) ) intu = bool( re.search( r"\b(intuition (?:first|before (?:the\s+)?(?:math|formal|proof|details?))|" r"big[- ]picture (?:first|before|then)|" r"high[- ]level intuition (?:first|before)|" r"motivation before (?:the\s+)?(?:formal|proof|math)|" r"informal (?:picture|overview) before|" r"start with (?:the\s+)?(?:big\s+picture|intuition|high[- ]level sketch)|" r"warm(?:\s+up)? with (?:an?\s+)?intuitive)\b", m, ) ) if defn and intu: return None if defn: return "definitions_first" if intu: return "intuition_first" return None def _embedded_glossary_section(m: str) -> tuple[str, str] | None: """``glossary`` — include a short glossary / key-terms definitions section.""" if len(m) < 48: return None no_glossary = bool( re.search( r"\b(no glossary|without glossary|skip glossary|avoid glossary|don'?t (?:include|add) glossary)\b", m, ) ) if no_glossary: return None no_headings = bool( re.search( r"\b(flat answer|no section headings|avoid markdown headings|continuous prose only|prose without headings)\b", m, ) ) want = bool( re.search( r"\b(glossary(?:[- ]style)?|provide (?:a )?glossary|include (?:a )?glossary|" r"terms and definitions|define (?:the )?(?:key )?terms)\b", m, ) ) if not want or no_headings: return None instr = ( "The user requested a **Glossary**: include a short **Glossary** section defining 3–8 " "key terms mentioned in the prompt (especially jargon). Provide each definition as a " "single concise sentence." ) return instr, "glossary" def _embedded_spelling_locale(m: str) -> tuple[str, str] | None: """``spelling_uk`` / ``spelling_us`` — British vs American English spelling in the reply.""" if len(m) < 44: return None uk = bool( re.search( r"\b(british english|uk english|uk spelling|british spelling|" r"use british spellings?|spell(?:ing)? (?:in )?british english|" r"en[- ]?gb (?:spelling|english)|" r"colour not color|favour not favor|organise not organize)\b", m, ) ) us = bool( re.search( r"\b(american english|us english|us spelling|american spelling|" r"use american spellings?|spell(?:ing)? (?:in )?american english|" r"en[- ]?us (?:spelling|english)|" r"color not colour|favor not favour|organize not organise)\b", m, ) ) if uk and us: return None if uk: instr = ( "The user asked for **British English (UK) spelling** throughout the reply " "(e.g. colour, organise, centre, licence)—not US forms unless quoting source text verbatim." ) return instr, "spelling_uk" if us: instr = ( "The user asked for **American English (US) spelling** throughout the reply " "(e.g. color, organize, center, license)—not UK forms unless quoting source text verbatim." ) return instr, "spelling_us" return None def _embedded_timeline_order(m: str) -> tuple[str, str] | None: """``timeline_chron`` / ``timeline_reverse`` — chronological vs reverse-chronological event layout.""" if len(m) < 48: return None if re.search( r"\b(no timeline|not a timeline|without a timeline|skip (?:the )?timeline|" r"don'?t use a timeline)\b", m, ): return None reverse = bool( re.search( r"\b(reverse chronological|anti[- ]chronological|newest first|most recent first|" r"latest first|work backwards|backward in time|from latest to earliest|" r"most recent event first)\b", m, ) ) chron = bool( re.search( r"\b(?:in chronological order|(? tuple[str, str] | None: """``voice_second`` / ``voice_third`` — address reader as *you* vs impersonal third person.""" if len(m) < 48: return None third = bool( re.search( r"\b(third person|3rd person|impersonal tone|impersonal voice|" r"don'?t address (?:the )?reader as you|avoid second person|" r"no second person|don'?t use (?:you|your) (?:throughout|in the reply)|" r"refer to (?:the )?user(?:s)? not you|neutral documentation voice|" r"formal documentation style.{0,30}not you)\b", m, ) ) second = bool( re.search( r"\b(?:(? tuple[str, str] | None: """``faq_qa`` — reply as explicit question-and-answer pairs (``Q:`` / ``A:`` layout).""" if len(m) < 48: return None no_qa = bool( re.search( r"\b(no q&a format|not q&a format|without q&a|skip q&a format|" r"don'?t use q&a|prose not q&a|not in q&a format|" r"no question[- ]and[- ]answer pairs?|avoid q&a layout)\b", m, ) ) if no_qa: return None want = bool( re.search( r"\b(q&a format|question[- ]and[- ]answer format|questions? and answers? format|" r"format as q&a|faq[- ]style q&a|faq q&a layout|" r"each question (?:with|followed by) (?:an )?answer|" r"question answer pairs?|q:\s*/\s*a: layout|" r"use q:\s*and a:\s*headings|pair each question with an answer)\b", m, ) ) if not want: return None if not re.search( r"\b(explain|describe|write|draft|document|outline|prepare|" r"faq|support|customer|policy|helpdesk|knowledge base|kb)\b", m, ): return None instr = ( "The user wants a **FAQ Q&A layout**: structure the reply as clear **question → answer** " "pairs using markdown labels **Q:** and **A:** (or **Question** / **Answer** headings); " "keep each answer concise under its question—not one undifferentiated essay." ) return instr, "faq_qa" def _embedded_summary_last(m: str) -> tuple[str, str] | None: """``summary_last`` — close the reply with a brief recap (complement to ``answer_lead=tldr_first``).""" if len(m) < 44: return None no_end = bool( re.search( r"\b(no summary at the end|skip (?:the )?(?:closing|final) summary|" r"don'?t (?:add|end with) a (?:tldr|summary) at the end|" r"without a closing summary|no recap at the end)\b", m, ) ) if no_end: return None tldr_first = bool( re.search( r"\b(tl;?dr first|tldr first|summary first|executive summary first|" r"bottom line up front|\bbluf\b|lead with (?:a\s+)?(?:one[- ]line\s+)?summary|" r"(?:key\s+)?takeaway first|headline first)\b", m, ) ) end_sum = bool( re.search( r"\b(summary at the end|tldr at the (?:bottom|end)|executive summary at the end|" r"wrap up with (?:a\s+)?(?:brief\s+)?summary|close with (?:a\s+)?(?:one[- ]line\s+)?summary|" r"end with (?:a\s+)?(?:brief\s+)?(?:summary|tldr|recap|key takeaway)|" r"recap at the (?:bottom|end)|closing summary|final summary (?:line|paragraph))\b", m, ) ) if not end_sum or tldr_first: return None if not re.search( r"\b(explain|describe|write|draft|summarize|report|outline|brief|memo|answer|" r"analysis|review|compare|recommend)\b", m, ): return None instr = ( "The user wants a **closing summary**: after the main answer, end with a short " "**Summary** or **TL;DR** line (1–3 sentences) that recaps the key takeaway—" "do **not** open with that recap (unless they also asked for BLUF elsewhere)." ) return instr, "summary_last" def _embedded_decision_matrix(m: str) -> tuple[str, str] | None: """``decision_matrix`` — criteria × options markdown table for side-by-side evaluation.""" if len(m) < 48: return None no_matrix = bool( re.search( r"\b(no decision matrix|without a (?:decision|comparison|feature) matrix|" r"not a (?:decision|comparison|feature) matrix|skip the matrix|" r"don'?t use a (?:decision|comparison|feature) matrix|" r"avoid a (?:decision|comparison|feature) matrix|" r"no matrix (?:format|table))\b", m, ) ) if no_matrix: return None want = bool( re.search( r"\b(decision matrix|comparison matrix|feature matrix|" r"evaluation matrix|criteria matrix|" r"score each option (?:on|against|across)|" r"matrix (?:comparing|of) (?:the )?(?:options|vendors|tools|alternatives|platforms)|" r"options (?:as|in) columns?(?: and criteria as rows?)?|" r"criteria (?:as|in) rows?(?: and options as columns?)?|" r"side[- ]by[- ]side matrix|" r"rate each option (?:on|against) (?:each|the) criteri(?:a|on))\b", m, ) ) if not want: return None if not re.search( r"\b(compare|choose|pick|select|evaluate|decide|recommend|rank|" r"vendor|tool|option|alternative|approach|platform|solution)\b", m, ): return None instr = ( "The user wants a **decision matrix**: include a markdown **table** with **options/alternatives " "as columns** and **evaluation criteria as rows** (cells: short scores, ratings, or ✓/✗). " "Add a one-line legend if you use symbols; keep supporting prose outside the table." ) return instr, "decision_matrix" def _embedded_build_vs_buy(m: str) -> tuple[str, str] | None: """``build_vs_buy`` — structured Build (in-house) vs Buy (vendor/SaaS) decision layout.""" if len(m) < 48: return None no_bvb = bool( re.search( r"\b(no build[- ]vs[- ]buy|without (?:a\s+)?build[- ]vs[- ]buy|" r"skip (?:the\s+)?build[- ]vs[- ]buy|not a build[- ]vs[- ]buy|" r"don'?t use build[- ]vs[- ]buy|avoid build[- ]vs[- ]buy (?:analysis|section)|" r"no make[- ]vs[- ]buy section)\b", m, ) ) if no_bvb: return None want = bool( re.search( r"\b(build[- ]vs[- ]buy|build[- ]versus[- ]buy|make[- ]vs[- ]buy|make[- ]versus[- ]buy|" r"build or buy|make or buy|" r"in[- ]house vs (?:vendor|outsource|saas|third[- ]party)|" r"build in[- ]house (?:vs\.?|versus|or) (?:buy|purchase|vendor)|" r"custom build vs (?:commercial|off[- ]the[- ]shelf|saas|vendor)|" r"diy vs (?:buy|purchase|vendor solution))\b", m, ) ) if not want: return None if not re.search( r"\b(build|buy|vendor|outsource|saas|platform|tool|service|solution|" r"decide|evaluate|recommend|assess|choose|write|describe|outline|report|memo)\b", m, ): return None instr = ( "The user wants a **build vs buy** analysis: structure the answer with markdown headings " "**Build (in-house)** and **Buy (vendor/SaaS)** (bullets under each on cost, time, risk, " "and fit), then a brief **Recommendation** line—do not bury the choice after long background." ) return instr, "build_vs_buy" def _embedded_one_pager(m: str) -> tuple[str, str] | None: """``one_pager`` — single-page executive brief with fixed scannable sections.""" if len(m) < 48: return None no_op = bool( re.search( r"\b(no one[- ]pager|without (?:a\s+)?one[- ]pager|not a one[- ]pager|" r"skip (?:the\s+)?one[- ]pager|don'?t use one[- ]pager|" r"avoid one[- ]pager (?:format|section|layout)|" r"no single[- ]page (?:brief|memo format))\b", m, ) ) if no_op: return None bluf_first = bool( re.search( r"\b(tl;?dr first|tldr first|summary first|executive summary first|" r"bottom line up front|\bbluf\b|lead with (?:a\s+)?(?:one[- ]line\s+)?summary)\b", m, ) ) end_sum = bool( re.search( r"\b(summary at the end|tldr at the (?:bottom|end)|executive summary at the end|" r"wrap up with (?:a\s+)?(?:brief\s+)?summary|close with (?:a\s+)?(?:one[- ]line\s+)?summary)\b", m, ) ) if bluf_first or end_sum: return None want = bool( re.search( r"\b(one[- ]pager(?:\s+format|\s+memo|\s+brief|\s+summary)?|" r"one page (?:memo|brief|summary|write[- ]up|document)|" r"single[- ]page (?:brief|memo|summary|executive brief)|" r"executive one[- ]pager|" r"fit(?:s|ting)? on (?:a\s+)?single page|" r"one[- ]page (?:executive\s+)?(?:brief|memo|summary))\b", m, ) ) if not want: return None if not re.search( r"\b(write|draft|prepare|outline|describe|brief|memo|report|" r"leadership|executive|steering|board|stakeholder|committee|" r"initiative|program|proposal|decision|update)\b", m, ): return None instr = ( "The user wants a **one-pager** executive brief: use compact markdown headings " "**Title / Purpose**, **Context**, **Problem / Opportunity**, **Recommendation** " "(1–2 sentences), **Key points** (3–5 bullets), **Next steps**, and brief " "**Risks / dependencies**—keep it scannable on one screen; avoid long background prose." ) return instr, "one_pager" def _embedded_action_plan(m: str) -> tuple[str, str] | None: """``action_plan`` — actionable items with owners and due dates (not ``- [ ]`` checklists).""" if len(m) < 48: return None no_ap = bool( re.search( r"\b(no action plan|without (?:an\s+)?action plan|not an action plan|" r"skip (?:the\s+)?action plan|don'?t use action plan|" r"avoid action plan (?:format|section|table)|" r"no implementation plan (?:table|format))\b", m, ) ) if no_ap: return None checklist_only = bool( re.search( r"\b((?:as a|use a|markdown) checklist|checklist (?:format|style)|" r"tick[- ]box(?:es)?|checkbox(?:es)? (?:list|format))\b", m, ) ) if checklist_only: return None want = bool( re.search( r"\b(action plan(?:\s+format)?|implementation plan(?:\s+with)?(?:\s+)?owners|" r"who does what(?:\s+by when)?|owners? and (?:due dates?|deadlines?|timelines?)|" r"assign owners?(?:\s+and)?(?:\s+)?(?:due dates?|deadlines?)|" r"delivery plan with owners|work plan with (?:owners|assignees)|" r"table of actions? (?:with|and) (?:owners?|due dates?))\b", m, ) ) if not want: return None if not re.search( r"\b(rollout|deploy|launch|migrate|implement|project|program|initiative|" r"sprint|workstream|deliverable|plan|outline|write|describe|track|execute)\b", m, ): return None instr = ( "The user wants an **action plan**: list actionable items in a markdown **table** " "(or clearly labeled rows) with **Action**, **Owner** (role/team), **Due / target date** " "(or phase), and brief **Notes** if needed—group by phase when useful; " "use **not** `- [ ]` checkbox checklists unless they also asked for tick-boxes." ) return instr, "action_plan" def _embedded_raci_matrix(m: str) -> tuple[str, str] | None: """``raci`` — Responsible / Accountable / Consulted / Informed role assignment table.""" if len(m) < 48: return None no_raci = bool( re.search( r"\b(no raci|without (?:a\s+)?raci|not a raci|skip (?:the\s+)?raci|" r"don'?t use raci|avoid raci (?:matrix|chart|table)|" r"no raci (?:matrix|chart|table|section))\b", m, ) ) if no_raci: return None want = bool( re.search( r"\b(raci matrix|raci chart|raci table|raci format|" r"responsible[, ]+accountable[, ]+consulted[, ]+(?:and )?informed|" r"\braci\b.{0,40}(?:responsible|accountable|consulted|informed)|" r"r\s*\/\s*a\s*\/\s*c\s*\/\s*i (?:matrix|roles|chart)|" r"who is (?:responsible|accountable) (?:vs\.?|and|versus) (?:consulted|informed)|" r"assign (?:raci|r\s*\/\s*a\s*\/\s*c\s*\/\s*i) roles)\b", m, ) ) if not want: return None if not re.search( r"\b(project|rollout|migration|initiative|workstream|deliverable|team|" r"launch|deployment|program|plan|outline|write|describe|assign|ownership)\b", m, ): return None instr = ( "The user wants a **RACI matrix**: include a markdown **table** with rows for key " "tasks/workstreams and columns **R** (Responsible), **A** (Accountable), **C** (Consulted), " "**I** (Informed)—use role names or teams in cells; add a one-line legend if needed." ) return instr, "raci" def _embedded_stakeholder_map(m: str) -> tuple[str, str] | None: """``stakeholder_map`` — influence/interest stakeholder table (distinct from ``raci`` task roles).""" if len(m) < 48: return None no_sm = bool( re.search( r"\b(no stakeholder map|without (?:a\s+)?stakeholder map|not a stakeholder map|" r"skip (?:the\s+)?stakeholder map|don'?t use stakeholder map|" r"avoid stakeholder (?:map|matrix|analysis)|" r"no stakeholder (?:map|matrix|analysis format))\b", m, ) ) if no_sm: return None raci_only = bool( re.search( r"\b(raci matrix|raci chart|raci table|" r"responsible[, ]+accountable[, ]+consulted[, ]+(?:and )?informed|" r"r\s*\/\s*a\s*\/\s*c\s*\/\s*i (?:matrix|roles|chart))\b", m, ) ) if raci_only: return None want = bool( re.search( r"\b(stakeholder map(?:\s+format)?|stakeholder matrix|stakeholder analysis|" r"map (?:the\s+)?stakeholders?|stakeholder mapping|" r"influence[- ](?:interest|impact) (?:matrix|grid|map)|" r"power[- ]interest (?:matrix|grid|map)|" r"interest[- ]influence (?:matrix|grid)|" r"who (?:are|is) (?:the\s+)?stakeholders? (?:and|with) (?:their\s+)?(?:influence|interests))\b", m, ) ) if not want: return None if not re.search( r"\b(project|rollout|migration|initiative|program|change|launch|" r"communicate|engage|adopt|implement|outline|write|describe|plan|announce)\b", m, ): return None instr = ( "The user wants a **stakeholder map**: include a markdown **table** with columns " "**Stakeholder / group**, **Interest**, **Influence** (High/Med/Low), **Key concerns**, " "and **Engagement approach**—optionally add a one-line **Power–Interest** quadrant note; " "this is **not** a RACI task-assignment matrix." ) return instr, "stakeholder_map" def _embedded_swot_analysis(m: str) -> tuple[str, str] | None: """``swot`` — Strengths / Weaknesses / Opportunities / Threats strategic layout.""" if len(m) < 48: return None no_swot = bool( re.search( r"\b(no swot|without (?:a\s+)?swot|not a swot|skip (?:the\s+)?swot|" r"don'?t use swot|avoid swot|no swot (?:format|section|framework))\b", m, ) ) if no_swot: return None want = bool( re.search( r"\b(swot analysis|swot format|swot framework|swot breakdown|" r"strengths[, ]+weaknesses[, ]+opportunities[, ]+(?:and )?threats|" r"strengths weaknesses opportunities threats|" r"s\.w\.o\.t\.|" r"\bswot\b.{0,40}(?:strengths|weaknesses|opportunities|threats))\b", m, ) ) if not want: return None if not re.search( r"\b(analy(?:s|z)e|analysis|assess|evaluate|review|plan|strategy|launch|" r"product|initiative|market|competitive|position|expansion|rollout|" r"describe|write|outline|report|memo)\b", m, ): return None instr = ( "The user wants a **SWOT analysis**: structure the answer with markdown headings " "**Strengths**, **Weaknesses**, **Opportunities**, and **Threats** (bullets under each). " "Focus on one subject (product, team, initiative, or market position)—not a generic essay." ) return instr, "swot" def _embedded_pestle_analysis(m: str) -> tuple[str, str] | None: """``pestle`` — Political / Economic / Social / Technological / Legal / Environmental macro scan.""" if len(m) < 48: return None no_pestle = bool( re.search( r"\b(no pestle|without (?:a\s+)?pestle|not a pestle|skip (?:the\s+)?pestle|" r"don'?t use pestle|avoid pestle|no pestle (?:format|section|framework))\b", m, ) ) if no_pestle: return None want = bool( re.search( r"\b(pestle analysis|pestle format|pestle framework|pestle breakdown|" r"political[, ]+economic[, ]+social[, ]+technological[, ]+legal[, ]+(?:and )?environmental|" r"political economic social technological legal environmental|" r"p\.e\.s\.t\.l\.e\.|" r"\bpestle\b.{0,40}(?:political|economic|social|technological|legal|environmental))\b", m, ) ) if not want: return None if not re.search( r"\b(analy(?:s|z)e|analysis|assess|evaluate|review|plan|strategy|market|" r"expansion|entry|regulatory|policy|macro|environment|industry|" r"describe|write|outline|report|memo|initiative)\b", m, ): return None instr = ( "The user wants a **PESTLE analysis**: structure the answer with markdown headings " "**Political**, **Economic**, **Social**, **Technological**, **Legal**, and **Environmental** " "(bullets under each). Focus on external macro factors affecting one market or initiative." ) return instr, "pestle" def _embedded_cost_benefit(m: str) -> tuple[str, str] | None: """``cost_benefit`` — structured costs vs benefits analysis for business cases.""" if len(m) < 48: return None no_cb = bool( re.search( r"\b(no cost[- ]benefit|without (?:a\s+)?cost[- ]benefit|" r"skip (?:the\s+)?cost[- ]benefit|not a cost[- ]benefit|" r"don'?t use cost[- ]benefit|avoid cost[- ]benefit (?:format|section)|" r"no cba section|skip (?:the\s+)?cba)\b", m, ) ) if no_cb: return None want = bool( re.search( r"\b(cost[- ]benefit analysis|cost benefit analysis|" r"costs? and benefits? (?:analysis|breakdown|section)|" r"benefits? (?:and|vs\.?) costs? (?:analysis|breakdown)|" r"\bcba\b (?:format|analysis|section)|" r"weigh (?:the\s+)?costs? against (?:the\s+)?benefits?|" r"weigh benefits? against costs?|" r"costs? versus benefits? (?:analysis|comparison))\b", m, ) ) if not want: return None if not re.search( r"\b(project|proposal|invest|build|migrate|rollout|initiative|business case|" r"strategy|plan|evaluate|assess|decide|recommend|write|describe|outline|report|memo)\b", m, ): return None instr = ( "The user wants a **cost-benefit analysis**: structure the answer with markdown headings " "**Costs** and **Benefits** (bullets under each), then a brief **Net assessment** line " "comparing them—keep dollar/time estimates qualitative unless the user supplied numbers." ) return instr, "cost_benefit" def _embedded_open_questions(m: str) -> tuple[str, str] | None: """``open_questions`` — end section listing unresolved unknowns / TBD items (not user-facing closers).""" if len(m) < 48: return None no_oq = bool( re.search( r"\b(no open questions?|without (?:an?\s+)?open questions? section|" r"skip (?:the\s+)?open questions?|don'?t (?:include|list) open questions?|" r"not an open questions? section|avoid (?:an?\s+)?open questions? section|" r"no tbd section|skip (?:the\s+)?(?:tbd|unknowns?) section)\b", m, ) ) if no_oq: return None want = bool( re.search( r"\b(open questions? section|include (?:an?\s+)?open questions?|" r"list (?:the\s+)?open questions?|outstanding questions?|unresolved questions?|" r"questions? (?:we )?still need (?:to )?(?:answer|resolve)|" r"what(?:'s| is) still (?:unknown|tbd|unclear)|" r"(?:information|info) gaps?(?: to (?:flag|note))?|" r"unknowns? (?:to|we still need to) (?:flag|resolve|clarify)|" r"tbd items?(?: at the end)?|" r"end with (?:an?\s+)?open questions? section)\b", m, ) ) if not want: return None if not re.search( r"\b(plan|proposal|memo|report|outline|draft|review|analysis|initiative|" r"rollout|strategy|design|recommend|assess|evaluate|write|describe|explain)\b", m, ): return None instr = ( "The user wants an **Open questions** section: after the main answer, add a heading " "**Open questions** with 3–6 bullet points listing **unresolved unknowns**, missing data, " "or decisions still TBD—do **not** use this section to ask the user rhetorical follow-ups " "or stock closers like “let me know if you need more.”" ) return instr, "open_questions" def _embedded_scenario_cases(m: str) -> tuple[str, str] | None: """``scenario_cases`` — Best / base / worst case (or similar) multi-scenario breakdown.""" if len(m) < 48: return None no_sc = bool( re.search( r"\b(no scenarios?|without (?:a\s+)?scenario analysis|skip (?:the\s+)?scenario(?:s)?|" r"don'?t use scenarios?|avoid scenario analysis|not a scenario analysis|" r"single scenario only|one scenario only|no best[- ]case section)\b", m, ) ) if no_sc: return None want = bool( re.search( r"\b(best[- ]case(?:\s*[/,&]\s*(?:base|worst)[- ]case)?|" r"worst[- ]case(?:\s*[/,&]\s*(?:base|best)[- ]case)?|" r"base[- ]case(?:\s*[/,&]\s*(?:best|worst)[- ]case)?|" r"best,?\s+base,?\s+(?:and\s+)?worst[- ]case|" r"optimistic,?\s+(?:realistic|base)[, ]+(?:and\s+)?pessimistic|" r"scenario analysis|three scenarios?|3 scenarios?|" r"multiple scenarios?|range of outcomes?|" r"upside[- ]downside[- ]base|bull[- ]base[- ]bear case)\b", m, ) ) if not want: return None if not re.search( r"\b(plan|forecast|budget|revenue|growth|launch|initiative|rollout|strategy|" r"project|invest|risk|outlook|memo|report|analysis|assess|evaluate|describe|write|explain)\b", m, ): return None instr = ( "The user wants a **scenario analysis**: structure the answer with markdown headings " "**Best case**, **Base case**, and **Worst case** (or clearly labeled optimistic / " "realistic / pessimistic scenarios). Under each, give 2–4 bullet points on outcomes, " "assumptions, and key triggers—keep it focused on one decision or initiative." ) return instr, "scenario_cases" def _embedded_postmortem_format(m: str) -> tuple[str, str] | None: """``postmortem`` — blameless incident postmortem scaffold (SRE-style sections).""" if len(m) < 48: return None no_pm = bool( re.search( r"\b(no postmortem|without (?:a\s+)?postmortem|not a postmortem|" r"skip (?:the\s+)?postmortem|don'?t use postmortem format|" r"avoid postmortem (?:format|sections|template)|" r"no post[- ]mortem (?:format|template|sections))\b", m, ) ) if no_pm: return None want = bool( re.search( r"\b(postmortem format|post[- ]mortem format|blameless postmortem|" r"blameless post[- ]mortem|incident postmortem|postmortem template|" r"post[- ]mortem template|postmortem outline|structure (?:as|in) a postmortem|" r"write (?:it\s+)?(?:as|in) postmortem format|" r"postmortem.{0,50}(?:lessons learned|root cause|action items))\b", m, ) ) if not want: return None if not re.search( r"\b(incident|outage|failure|on[- ]call|sre|deploy|rollback|downtime|" r"sev[0-9]|production|service|system|write|draft|outline|describe|explain|report)\b", m, ): return None instr = ( "The user wants a **blameless postmortem** layout: use markdown headings " "**Summary**, **Impact**, **Timeline**, **Root cause**, **Lessons learned**, and " "**Action items** (short bullets under each). Stay factual and avoid blaming individuals." ) return instr, "postmortem" def _embedded_sprint_retro(m: str) -> tuple[str, str] | None: """``sprint_retro`` — agile sprint retrospective layout (distinct from incident ``postmortem``).""" if len(m) < 48: return None no_sr = bool( re.search( r"\b(no sprint retro|without (?:a\s+)?sprint retro|not a sprint retro|" r"skip (?:the\s+)?sprint retro|don'?t use sprint retro|" r"avoid sprint retro(?:spective)? (?:format|sections)|" r"no (?:sprint\s+)?retrospective format|" r"skip (?:the\s+)?(?:sprint\s+)?retrospective format)\b", m, ) ) if no_sr: return None postmortem_only = bool( re.search( r"\b(postmortem format|blameless postmortem|incident postmortem|" r"post[- ]mortem format|postmortem outline)\b", m, ) ) if postmortem_only: return None want = bool( re.search( r"\b(sprint retro(?:spective)?(?:\s+format)?|" r"sprint retrospective(?:\s+format)?|" r"agile retro(?:spective)?|scrum retro(?:spective)?|" r"retro format|retrospective format|" r"run (?:a\s+)?(?:sprint\s+)?retro(?:spective)?|" r"facilitate (?:a\s+)?(?:sprint\s+)?retro(?:spective)?)\b", m, ) ) if not want: return None if not re.search( r"\b(sprint|iteration|scrum|agile|team|delivery|release|" r"reflect|review|improve|outline|write|describe|facilitate|discuss)\b", m, ): return None instr = ( "The user wants a **sprint retrospective** layout: use markdown headings " "**Sprint / period** (one line), **What went well**, **What didn't go well**, " "**Ideas / experiments**, and **Action items** (concrete next-sprint improvements)—" "stay blameless and team-focused; this is **not** an incident postmortem." ) return instr, "sprint_retro" def _embedded_user_story(m: str) -> tuple[str, str] | None: """``user_story`` — agile As a / I want / So that stories with acceptance criteria.""" if len(m) < 48: return None no_us = bool( re.search( r"\b(no user stor(?:y|ies)|without user stor(?:y|ies)|not user stor(?:y|ies)|" r"skip (?:the\s+)?user stor(?:y|ies)|don'?t use user stor(?:y|ies)|" r"avoid user story (?:format|template)|" r"no user story format|skip (?:the\s+)?user story format)\b", m, ) ) if no_us: return None star_only = bool( re.search( r"\b(star format|star method|situation[- ]task[- ]action[- ]result)\b", m, ) ) if star_only: return None want = bool( re.search( r"\b(user stor(?:y|ies)(?:\s+format)?|" r"write (?:the\s+)?user stor(?:y|ies)|" r"draft (?:the\s+)?user stor(?:y|ies)|" r"backlog (?:user\s+)?stor(?:y|ies)|" r"as an? .{0,48} i want .{0,72} so that|" r"acceptance criteria (?:for|per) (?:each|the) (?:user\s+)?stor(?:y|ies)|" r"in user story format|user story template)\b", m, ) ) if not want: return None if not re.search( r"\b(backlog|sprint|product|feature|agile|scrum|requirement|" r"pm|develop|implement|write|draft|describe|outline|plan|sso|login|flow)\b", m, ): return None instr = ( "The user wants **user stories**: for each story use a short **Title**, then " "**As a** … **I want** … **So that** … on separate lines, and **Acceptance criteria** " "(3–5 testable bullets or compact Given/When/Then)—INVEST-sized, not essay requirements." ) return instr, "user_story" def _embedded_definition_of_done(m: str) -> tuple[str, str] | None: """``definition_of_done`` — agile DoD checklist of verifiable completion criteria.""" if len(m) < 48: return None no_dod = bool( re.search( r"\b(no definition of done|without (?:a\s+)?definition of done|" r"not a definition of done|skip (?:the\s+)?definition of done|" r"don'?t use definition of done|avoid definition of done (?:format|section)|" r"no dod format|skip (?:the\s+)?dod format|" r"no done criteria section|skip (?:the\s+)?done criteria section)\b", m, ) ) if no_dod: return None checklist_only = bool( re.search( r"\b((?:as a|use a|markdown) checklist|checklist (?:format|style)|" r"tick[- ]box(?:es)?|checkbox(?:es)? (?:list|format))\b", m, ) ) if checklist_only: return None want = bool( re.search( r"\b(definition of done(?:\s+format)?|definition[- ]of[- ]done|" r"\bdod\b(?:\s+format|\s+checklist|\s+criteria)?|" r"done criteria(?:\s+checklist)?|" r"what counts as done|exit criteria (?:for|on) (?:the\s+)?(?:story|sprint|feature|epic|release)|" r"completion criteria (?:for|before)|" r"ready for (?:done|merge|release) criteria)\b", m, ) ) if not want: return None if not re.search( r"\b(sprint|story|epic|feature|backlog|agile|scrum|team|deliverable|" r"ship|merge|release|implement|write|draft|describe|outline|align)\b", m, ): return None instr = ( "The user wants a **Definition of Done**: use a **Definition of Done** heading with a " "one-line **Scope** (story / sprint / release), then 5–10 **Done criteria** as " "verifiable bullets (code review, tests, docs, deploy, sign-off, etc.)—concrete and " "checkable; distinct from per-story **acceptance criteria** unless they asked for both." ) return instr, "definition_of_done" def _embedded_five_whys(m: str) -> tuple[str, str] | None: """``five_whys`` — iterative Why chain for root-cause analysis (distinct from full postmortem).""" if len(m) < 48: return None no_fw = bool( re.search( r"\b(no five whys|no 5 whys|without five whys|skip (?:the\s+)?(?:five|5) whys|" r"don'?t use (?:the\s+)?(?:five|5) whys|avoid five whys|" r"not a five whys|no why chain|skip (?:the\s+)?why chain)\b", m, ) ) if no_fw: return None want = bool( re.search( r"\b(five whys|5 whys|five[- ]whys analysis|5[- ]whys analysis|" r"five whys (?:method|technique|root cause)|" r"root cause (?:using|with|via) (?:the\s+)?(?:five|5) whys|" r"ask why (?:five|5) times|why chain analysis|" r"iterative whys?|successive whys?)\b", m, ) ) if not want: return None if not re.search( r"\b(incident|outage|failure|bug|defect|problem|issue|root cause|" r"debug|diagnose|explain|investigate|analyze|analysis|why did|what caused)\b", m, ): return None instr = ( "The user wants a **5 Whys** root-cause analysis: start with a one-line **Problem statement**, " "then numbered **Why 1** … **Why 5** (each answer feeds the next why; stop early if the root " "is clear), and end with a **Root cause** summary line—stay blameless and factual." ) return instr, "five_whys" def _embedded_fishbone(m: str) -> tuple[str, str] | None: """``fishbone`` — Ishikawa cause-and-effect diagram by category (complements ``five_whys``).""" if len(m) < 48: return None no_fb = bool( re.search( r"\b(no fishbone|without (?:a\s+)?fishbone|not a fishbone|" r"skip (?:the\s+)?fishbone|don'?t use fishbone|" r"avoid fishbone (?:diagram|analysis|format)|" r"no ishikawa (?:diagram|analysis)|" r"no cause[- ]and[- ]effect diagram)\b", m, ) ) if no_fb: return None want = bool( re.search( r"\b(fishbone (?:diagram|analysis|chart|format)|" r"ishikawa (?:diagram|analysis|chart|format)|" r"cause[- ]and[- ]effect (?:diagram|analysis|chart)|" r"fishbone.{0,40}(?:root cause|categories|6m|6 m)|" r"6\s*m(?:s)? (?:fishbone|analysis|diagram)|" r"diagram the causes? (?:by|into) categories)\b", m, ) ) if not want: return None if not re.search( r"\b(incident|outage|failure|defect|bug|problem|issue|quality|" r"process|production|root cause|analyze|analysis|investigate|" r"explain|describe|outline|diagnose|why did|what caused)\b", m, ): return None instr = ( "The user wants a **fishbone (Ishikawa)** cause-and-effect analysis: start with " "**Problem / Effect** (one line), then markdown headings for cause categories " "(e.g. **People**, **Process**, **Technology**, **Environment**, **Materials/Data**, " "**Management/Policy**) with 2–4 sub-cause bullets under each; end with a brief " "**Likely root cause** line—stay blameless; optional compact ASCII spine is fine." ) return instr, "fishbone" def _embedded_followup_close(m: str) -> str | None: """``minimal`` vs ``suggest`` from prose (not short *No follow-up questions* controls).""" if len(m) < 48: return None minimal = bool( re.search( r"\b(no questions? at the end|don'?t (?:ask|end) with (?:a\s+)?questions?|" r"don'?t ask if i need (?:anything|more) else|don'?t ask whether i need more|" r"skip (?:the\s+)?(?:stock\s+)?closer|no follow[- ]up questions (?:at\s+the\s+)?(?:end|please)?|" r"don'?t prompt for follow[- ]ups?|finish crisply|stop after the core answer|" r"avoid rhetorical closers?|no offers? to help further|" r"don'?t (?:close|end) with (?:an?\s+)?(?:offer|invitation) to continue)\b", m, ) ) suggest = bool( re.search( r"\b(suggest next steps|optional next steps at the end|" r"end with (?:brief\s+)?(?:actionable\s+)?next steps|" r"close with suggested next actions|what should we do next|" r"offer ways to go deeper|give me follow[- ]ups? i can take|" r"recommend what to do next|include (?:optional\s+)?next steps)\b", m, ) ) if minimal and suggest: return None if minimal: return "minimal" if suggest: return "suggest" return None def _embedded_clarify_first(m: str) -> str | None: """``on`` vs ``off`` from prose (not short *Clarify first* / *No clarifying questions* controls).""" if len(m) < 48: return None off = bool( re.search( r"\b(no clarifying questions (?:first|please)?|don'?t ask clarifying questions|" r"skip clarifying questions|answer without asking questions first|" r"don'?t (?:pause to\s+)?ask questions first|" r"give (?:your\s+)?best answer without asking|" r"don'?t interrogate me first|skip the q&a preamble|" r"answer immediately (?:even\s+)?if (?:the\s+)?(?:spec|specs) (?:is|are) incomplete)\b", m, ) ) on = bool( re.search( r"\b(ask clarifying questions before (?:you\s+)?answer|" r"clarify (?:any\s+)?ambiguities before|" r"if anything is unclear ask me first|" r"before you (?:answer|dive in) ask (?:me\s+)?(?:what\s+you\s+need|any questions)|" r"pause and ask (?:me\s+)?(?:short\s+)?questions if|" r"confirm my (?:constraints|requirements) before|" r"ask what you need (?:to know )?first|" r"i may have left details out[-—]\s*ask|" r"feel free to ask (?:me\s+)?(?:1[-–]3\s+)?clarifying questions first)\b", m, ) ) if on and off: return None if off: return "off" if on: return "on" return None def _embedded_section_headings(m: str) -> str | None: """``prefer`` vs ``avoid`` for markdown ##/### structure (not short *Use section headings* controls).""" if len(m) < 48: return None avoid = bool( re.search( r"\b(flat answer|no section headings|avoid markdown headings|" r"no (?:##|hash)\s*style headings|without (?:##|markdown) title lines|" r"continuous prose (?:only|without headings)|" r"don'?t use (?:leading\s+)?#+\s*headings?|" r"skip (?:the\s+)?##\s*headers?)\b", m, ) ) prefer = bool( re.search( r"\b(use (?:markdown\s+)?(?:section\s+)?headings|organize with (?:markdown\s+)?headings|" r"structure (?:the\s+)?answer with (?:clear\s+)?headings|" r"break (?:it|this|the answer) into (?:titled\s+)?sections|" r"(?:clear\s+)?markdown headings for each|" r"##\s*(?:or|/)\s*###\s*headings|" r"top[- ]level headings for each (?:major\s+)?(?:topic|section))\b", m, ) ) if avoid and prefer: return None if avoid: return "avoid" if prefer: return "prefer" return None def _embedded_analogy_use(m: str) -> str | None: """``prefer`` vs ``avoid`` for analogies/metaphors (not short *Use analogies* / *No analogies* controls).""" if len(m) < 48: return None avoid = bool( re.search( r"\b(no analogies|skip metaphors|avoid metaphors|skip the analogies|" r"without analogies or metaphors|literal (?:explanations?|wording) only|" r"don'?t use analogies|don'?t use metaphors|no cute comparisons|" r"stick to literal (?:technical\s+)?(?:language|description|wording)|" r"keep (?:it\s+)?strictly literal)\b", m, ) ) prefer = bool( re.search( r"\b(use (?:a\s+)?(?:helpful\s+|tight\s+)?analogy|" r"explain (?:it\s+)?with (?:a\s+)?(?:simple\s+)?(?:real[- ]world\s+)?analogy|" r"include (?:a\s+)?(?:brief\s+)?(?:metaphor|analogy)|" r"liken (?:this|it) to (?:something|a\s+familiar)|" r"compare (?:this|it)\s+to (?:a\s+)?(?:real[- ]world|everyday)|" r"map (?:this|it) to an everyday example|" r"metaphor that helps|ground (?:the\s+)?idea in (?:an?\s+)?analogy)\b", m, ) ) if avoid and prefer: return None if avoid: return "avoid" if prefer: return "prefer" return None def _embedded_term_emphasis(m: str) -> str | None: """``highlight`` vs ``minimal`` inline bold (not short *Bold key terms* controls).""" if len(m) < 48: return None minimal = bool( re.search( r"\b(minimal bold|don'?t overuse bold|avoid excessive bold|" r"sparse bold|keep bold (?:to a )?minimum|" r"no bold except (?:for )?code|plain text without bold|" r"don'?t bold every|avoid bolding (?:whole|entire) sentences)\b", m, ) ) highlight = bool( re.search( r"\b(bold (?:the\s+)?(?:key\s+)?terms|highlight (?:the\s+)?(?:key\s+)?(?:terms|phrases)|" r"emphasize (?:the\s+)?(?:key\s+)?(?:terms|keywords)|" r"make (?:the\s+)?key terms stand out|" r"use bold (?:on|for) (?:a\s+)?(?:few\s+)?(?:key\s+)?(?:terms|phrases|keywords)|" r"so (?:execs|leadership|managers) can scan.{0,50}bold)\b", m, ) ) if minimal and highlight: return None if minimal: return "minimal" if highlight: return "highlight" return None def _embedded_acronym_style(m: str) -> str | None: """``spell_out`` vs ``terse`` acronym handling (not short *Spell out acronyms* controls).""" if len(m) < 48: return None terse = bool( re.search( r"\b(assume (?:i|we) know acronyms|don'?t expand acronyms|" r"keep acronyms as[- ]is|skip acronym expansion|" r"no need to spell out acronyms|acronym[- ]literate (?:audience|readers?)|" r"terse acronyms only)\b", m, ) ) spell = bool( re.search( r"\b(spell out acronyms|expand acronyms (?:on|at) first use|" r"define acronyms when you (?:use|introduce)|" r"write out acronyms (?:on|at) first mention|" r"full form (?:once|on first mention).{0,40}(?:acronym|initialism)|" r"expand (?:each\s+)?(?:api|sla|sso|gdpr|hipaa|pci)[- ]style (?:term|acronym)|" r"for (?:auditors|compliance|non-technical).{0,50}spell out)\b", m, ) ) if spell and terse: return None if terse: return "terse" if spell: return "spell_out" return None def _embedded_risk_posture(m: str) -> str | None: """``conservative`` vs ``pragmatic`` recommendation tone (not short *Be risk averse* controls).""" if len(m) < 48: return None pragmatic = bool( re.search( r"\b(optimize for speed|good enough is fine|be pragmatic about|" r"avoid over[- ]engineering|ship (?:it )?fast|move fast (?:and|&)|" r"time[- ]efficient (?:fix|approach|recommendation)|" r"practical trade[- ]offs over perfection|" r"don'?t gold[- ]plate|bias toward shipping)\b", m, ) ) conservative = bool( re.search( r"\b(err on the side of safety|be risk[- ]averse|" r"risk[- ]averse (?:recommendation|approach)|" r"choose the (?:safest|lower[- ]risk) option|" r"minimize (?:downside|blast radius)|" r"prefer (?:safer|low[- ]risk) (?:options?|paths?)|" r"conservative (?:recommendation|rollout|approach)|" r"safety[- ]first (?:for|on) (?:this|the) (?:rollout|migration|change))\b", m, ) ) if conservative and pragmatic: return None if conservative: return "conservative" if pragmatic: return "pragmatic" return None def _embedded_quote_style(m: str) -> str | None: """``quote`` vs ``paraphrase`` when relying on supplied FAQ excerpts (not short *Quote the FAQ* controls).""" if len(m) < 48: return None src = r"(?:faq|excerpt|policy|knowledge base|kb article|documentation|provided (?:text|docs))" paraphrase = bool( re.search( rf"\b(paraphrase (?:the )?{src}|paraphrase only|" rf"(?:don'?t|do not) quote (?:the )?{src}|no direct quotes? from (?:the )?{src}|" rf"summarize (?:the )?{src} in your own words|" rf"avoid quoting (?:the )?{src}|in your own words.{0,40}(?:faq|excerpt))\b", m, ) ) quote = bool( re.search( rf"\b((? str | None: """``include`` vs ``avoid`` emoji in replies (not short *Use emoji* / *No emoji* controls).""" if len(m) < 48: return None avoid = bool( re.search( r"\b(no emojis? in (?:your|the) reply|avoid emoji|emoji[- ]free (?:reply|tone)|" r"don'?t use emoji|do not use emoji|keep (?:it\s+)?(?:strictly\s+)?professional.{0,40}no emoji|" r"without emoji|skip (?:the\s+)?emoji|no cute emoji|" r"plain text only.{0,30}no emoji)\b", m, ) ) include = bool( re.search( r"\b(use (?:a few\s+)?(?:tasteful\s+)?emoji|include emoji|emoji (?:are|is) ok|" r"emoji welcome|feel free to use emoji|sprinkle (?:in\s+)?emoji|" r"a few emoji (?:are|is) fine|light emoji (?:are|is) ok|" r"you may use emoji|add (?:a few\s+)?emoji (?:if|when) (?:helpful|appropriate))\b", m, ) ) if avoid and include: return None if avoid: return "avoid" if include: return "include" return None def _embedded_counterpoint_tone(m: str) -> str | None: """``challenge`` vs ``supportive`` pushback on plans (not short *Challenge my assumptions* controls).""" if len(m) < 52: return None ctx = ( r"\b(plan|plans|design|approach|idea|ideas|architecture|proposal|strategy|" r"implementation|rollout|pitch|deck|draft|thesis|launch|release|migration|schema|" r"deployment|code|system)\b" ) gentle = bool( re.search(r"\b(don'?t challenge|be gentle|go easy on me|no criticism|don'?t be harsh)\b", m) ) challenge = bool( not gentle and re.search( r"\b(red team|red-team|stress[- ]?test|pick apart|tear down|what am i missing|sanity check|" r"challenge my|poke holes|find (?:weaknesses|gaps|flaws)|critique (?:my|this|our)|" r"devil'?s advocate)\b", m, ) and re.search(ctx, m) ) supportive = bool( re.search( r"\b(be supportive (?:of|about|with)|assume good intent|encourage my (?:idea|plan|proposal)|" r"constructive and supportive|help me build on (?:this|my) (?:idea|plan)|" r"coach me through (?:this|my) (?:idea|plan|pitch)|" r"gentle (?:feedback|pushback) on (?:my|this|our)|" r"avoid harsh criticism|frame improvements as next steps|" r"lean supportive and (?:specific|actionable))\b", m, ) and re.search(ctx, m) ) if challenge and supportive: return None if challenge: return "challenge" if supportive: return "supportive" return None def _embedded_math_detail(m: str) -> str | None: """``show_work`` vs ``final_only`` for math-like answers (not short *Show your work* controls).""" if len(m) < 44: return None show = bool( re.search( r"\b(show your work|show (?:all )?(?:the )?steps|with (?:a )?derivation|prove (that|it)|rigorously|" r"walk through (?:the )?derivation|show intermediate steps|step[- ]by[- ]step derivation|" r"derive (?:it|the result) (?:step by step|explicitly))\b", m, ) ) final = bool( re.search( r"\b(final answer only|no derivation|skip (?:the )?steps|just (?:give )?(?:me )?the (?:final )?result|" r"don'?t show your work|do not show your work|answer without (?:showing )?steps|" r"no intermediate steps|closed[- ]form (?:answer|result) only|" r"(?:numerical |numeric )?answer only.{0,30}no steps)\b", m, ) ) if show and final: return None if show: return "show_work" if final and re.search( r"\b(math|equation|integral|derivative|probability|calculate|calculus|algebra|" r"proof|formula|theorem|matrix|solve|statistics|bayes|variance|expected value)\b", m, ): return "final_only" return None def _embedded_faq_grounding(m: str) -> str | None: """``strict`` vs ``relaxed`` FAQ/RAG grounding (not short *Strict FAQ* / *Relaxed FAQ* controls).""" if len(m) < 48: return None src = r"(?:faq|excerpt|policy|knowledge base|kb article|documentation|provided excerpts|retrieved passages)" strict = bool( re.search( rf"\b(stick to (?:the )?{src}|only use (?:the )?{src}|" rf"only trust (?:the )?{src}|faq[- ]only (?:for|on) (?:this|the)|" rf"strict faq (?:grounding|only)|if (?:it(?:'s| is) )?not in (?:the )?{src}.{0,40}(?:say|admit)|" rf"don'?t go beyond (?:the )?{src}|must be supported by (?:the )?{src}|" rf"policy claims must come from (?:the )?{src}|" rf"grounded strictly in (?:the )?{src})\b", m, ) ) relaxed = bool( re.search( rf"\b(faq plus general knowledge|mix (?:the )?{src} with general knowledge|" rf"relaxed faq (?:grounding|mode)|" rf"general knowledge (?:is )?ok.{0,50}(?:faq|excerpt|policy|documentation)|" rf"(?:faq|excerpt|policy|documentation).{0,50}general knowledge (?:is )?ok|" rf"supplement (?:the )?{src} with (?:brief )?general[- ]knowledge|" rf"beyond (?:the )?{src} you may add (?:brief )?general context)\b", m, ) ) if strict and relaxed: return None if strict: return "strict" if relaxed: return "relaxed" return None def _embedded_code_block_style(m: str) -> str | None: """``fenced`` vs ``inline`` code layout (not short *Use code fences* / *Inline code only* controls).""" if len(m) < 48: return None code_ctx = ( r"\b(code|snippet|command|script|bash|shell|python|curl|kubectl|docker|sql|" r"regex|yaml|terraform|powershell|config|api call|terminal)\b" ) fenced = bool( re.search( r"\b(use code fences|fenced code blocks?|markdown code fences?|" r"triple[- ]backtick fences?|put (?:the )?(?:code|commands?|script) in (?:a )?fenced block|" r"use markdown fenced code blocks?|wrap (?:the )?(?:code|snippet) in (?:triple )?backticks)\b", m, ) ) inline = bool( re.search( r"\b(inline code only|no triple backticks?|no fenced code blocks?|" r"avoid code fences|single backticks? only|don'?t use fenced blocks?|" r"keep (?:code|snippets?) inline|inline backticks? only)\b", m, ) ) if not fenced and not inline: return None if not re.search(code_ctx, m): return None if fenced and inline: return None if fenced: return "fenced" return "inline" def _embedded_reply_format(m: str) -> str | None: """``bullets`` vs ``prose`` list layout (not short *Use bullet points* / *No bullets* controls).""" if len(m) < 48: return None prose = bool( re.search( r"\b(no bullets?|plain paragraphs?|prose only|stop using lists|" r"continuous prose only|avoid bullet lists?|write in paragraphs|" r"paragraph form only|don'?t use bullet points?|" r"keep (?:it\s+)?in (?:flowing )?prose|not as a bulleted list)\b", m, ) ) bullets = bool( re.search( r"\b(bullet points?|bulleted list|use bullets|format as bullets|" r"list (?:the\s+)?key points in bullets|markdown bullets?|" r"give me a bulleted list|bullet(?:ed)? format)\b", m, ) ) if prose and bullets: return None if prose: return "prose" if bullets: return "bullets" return None def _embedded_comparison_frame(m: str) -> str | None: """``pros_cons`` vs ``narrative`` comparison layout (not short *Use pros and cons* controls).""" if len(m) < 48: return None if not re.search(r"\b(compare|comparing|comparison|contrasted?|contrast|trade-?offs?)\b", m): return None narrative = bool( re.search( r"\b(no pros|without pros|avoid pros|no pros\/cons|no pros and cons sections?)\b", m, ) or re.search( r"\b(flowing prose|continuous prose|narrative comparison|prose comparison only|" r"compare in flowing prose)\b", m, ) ) pros = bool( re.search( r"\b(trade-?offs?|(?= 72 and re.search( r"\b(versus|vs\.?|option|approach|tool|stack|framework|language|model|database|db|cloud)\b", m, ) ) ) if narrative and pros: return None if narrative: return "narrative" if pros: return "pros_cons" return None def _embedded_table_style(m: str) -> str | None: """``prefer`` vs ``avoid`` markdown tables (not short *Use tables* / *No tables* controls).""" if len(m) < 48: return None avoid = bool( re.search( r"\b(no tables?|without a table|avoid tables?|no markdown tables?|" r"don'?t use tables?|skip the table|table[- ]free (?:summary|answer)|" r"not in a table|avoid tabular format)\b", m, ) ) prefer = bool( re.search( r"\b(in a table|as a table|markdown table|(? str | None: """``numbered`` vs ``continuous`` procedure layout (not short *Step by step* controls).""" if len(m) < 48: return None continuous = bool( re.search( r"\b(no numbered steps|don'?t number steps|skip step numbers|" r"prose without steps|avoid numbered step lists?|" r"continuous prose (?:only|instead)|not as numbered steps|" r"connected paragraphs?(?:\s+only)?|explain as (?:flowing )?prose)\b", m, ) ) numbered = bool( re.search(r"\b(step by step|step-by-step)\b", m) or re.search(r"\b(walk me through|show me how)\b", m) or re.search(r"\b(? str | None: """Return display name (e.g. 'French') if the user asked for a reply in a known language.""" for mo in re.finditer( r"\b(respond|answer|reply|write|explain)\s+(?:in|using)\s+([a-z]{3,20})\b(?:\s*[.?!]|$|,|\s+please|\s+thanks)?", m, ): tok = mo.group(2) if tok in _REPLY_LANG_TOKENS: return _REPLY_LANG_TOKENS[tok] mo = re.search( r"\b(translate|translating)\s+(?:this|that|it|your answer|the above|my text)\s+(?:to|into)\s+([a-z]{3,20})\b", m, ) if mo and mo.group(2) in _REPLY_LANG_TOKENS: return _REPLY_LANG_TOKENS[mo.group(2)] mo = re.search(r"\b(entire reply|whole answer|full answer)\s+(?:in|using)\s+([a-z]{3,20})\b", m) if mo and mo.group(2) in _REPLY_LANG_TOKENS: return _REPLY_LANG_TOKENS[mo.group(2)] # Trailing clause: "... in french" / "... in spanish, please" tail = m[-100:] if len(m) > 100 else m mo = re.search(r"\b(in|into)\s+([a-z]{3,20})\s*(?:[,.]|please|thanks)?\s*$", tail) if mo and mo.group(2) in _REPLY_LANG_TOKENS: return _REPLY_LANG_TOKENS[mo.group(2)] return None def analyze_embedded_prompt_signals(message: str) -> tuple[dict[str, str], list[str], list[str]]: """Infer reply-style preferences from wording inside longer questions (one-shot overlays). Used only when ``parse_control_action`` does not treat the line as a dedicated control command. Conservative patterns avoid hijacking short chit-chat. Returns: (field_overrides, extra_system_paragraphs, trace_tags) — overrides use the same keys/values as ``ub_session`` reply-style fields; extra paragraphs are appended as separate system sections; ``trace_tags`` are short tokens for the brain-trace ``prompt_signals:`` line (e.g. ``language``, ``code_only``, ``code_explained``, ``len_cap=80w``, ``guided``, ``ephemeral``, ``a11y``, ``cite_sources``, ``cite_minimal``, ``ranked_options``, ``checklist``, ``no_checklist``, ``pseudocode``, ``runnable_code``, ``options_n=N``, ``diagram``, ``no_diagram``, ``risks_first``, ``benefits_first``, ``revise_draft``, ``revise_diff``, ``email_format``, ``letter_format``, ``press_release``, ``runbook_format``, ``job_aid``, ``meeting_agenda``, ``topic_guard``, ``topic_must``, ``glossary``, ``spelling_uk``, ``spelling_us``, ``risks_mitigations``, ``timeline_chron``, ``timeline_reverse``, ``voice_second``, ``voice_third``, ``faq_qa``, ``summary_last``, ``decision_matrix``, ``build_vs_buy``, ``one_pager``, ``status_report``, ``action_plan``, ``raci``, ``stakeholder_map``, ``swot``, ``pestle``, ``cost_benefit``, ``open_questions``, ``scenario_cases``, ``postmortem``, ``sprint_retro``, ``user_story``, ``definition_of_done``, ``five_whys``, ``fishbone``, ``recommendation_first``, ``go_no_go``, ``frame_star``, ``frame_prep``, ``frame_irac``). Session-style overrides (e.g. ``confidence_tone=transparent``) appear as ``key=value`` tokens in the same line. """ m = _norm(message) overrides: dict[str, str] = {} extras: list[str] = [] trace_tags: list[str] = [] if len(m) >= 24: lang = _reply_lang_phrase(m) if lang: trace_tags.append("language") extras.append( f"The user asked (via natural wording) for the assistant reply in **{lang}**. " f"Write the **entire** answer in {lang}, including headings and lists, unless a quoted passage must stay " "verbatim in another language." ) co = _code_only_instruction(m) cex = _embedded_code_commentary(m) if co and cex: pass elif co: trace_tags.append("code_only") extras.append(co) elif cex: extras.append(cex[0]) trace_tags.append(cex[1]) pc = _embedded_pseudocode(m) if pc and not (co or cex): extras.append(pc[0]) trace_tags.append(pc[1]) lc = _length_cap_instruction(m) if lc: extras.append(lc[0]) trace_tags.append(lc[1]) gdd = _embedded_guided_discovery(m) if gdd: extras.append(gdd[0]) trace_tags.append(gdd[1]) ep = _ephemeral_privacy_instruction(m) if ep: extras.append(ep[0]) trace_tags.append(ep[1]) ax = _accessibility_sr_instruction(m) if ax: extras.append(ax[0]) trace_tags.append(ax[1]) sc = _embedded_source_citations(m) if sc: extras.append(sc[0]) trace_tags.append(sc[1]) ro = _embedded_ranked_options(m) if ro: extras.append(ro[0]) trace_tags.append(ro[1]) dmx = _embedded_decision_matrix(m) if dmx: extras.append(dmx[0]) trace_tags.append(dmx[1]) bvb = _embedded_build_vs_buy(m) if bvb: extras.append(bvb[0]) trace_tags.append(bvb[1]) opg = _embedded_one_pager(m) if opg: extras.append(opg[0]) trace_tags.append(opg[1]) strpt = _embedded_status_report(m) if strpt: extras.append(strpt[0]) trace_tags.append(strpt[1]) apl = _embedded_action_plan(m) if apl: extras.append(apl[0]) trace_tags.append(apl[1]) rac = _embedded_raci_matrix(m) if rac: extras.append(rac[0]) trace_tags.append(rac[1]) stm = _embedded_stakeholder_map(m) if stm: extras.append(stm[0]) trace_tags.append(stm[1]) cl = _embedded_checklist_reply(m) if cl: extras.append(cl[0]) trace_tags.append(cl[1]) oc = _embedded_fixed_option_count(m) if oc: extras.append(oc[0]) trace_tags.append(oc[1]) dv = _embedded_diagram_visual(m) if dv: extras.append(dv[0]) trace_tags.append(dv[1]) rbo = _embedded_risks_benefits_order(m) if rbo: extras.append(rbo[0]) trace_tags.append(rbo[1]) rskm = _embedded_risks_mitigations(m) if rskm: extras.append(rskm[0]) trace_tags.append(rskm[1]) emf = _embedded_email_format(m) if emf: extras.append(emf[0]) trace_tags.append(emf[1]) ltf = _embedded_letter_format(m) if ltf: extras.append(ltf[0]) trace_tags.append(ltf[1]) prf = _embedded_press_release(m) if prf: extras.append(prf[0]) trace_tags.append(prf[1]) rbf = _embedded_runbook_format(m) if rbf: extras.append(rbf[0]) trace_tags.append(rbf[1]) jba = _embedded_job_aid(m) if jba: extras.append(jba[0]) trace_tags.append(jba[1]) mag = _embedded_meeting_agenda(m) if mag: extras.append(mag[0]) trace_tags.append(mag[1]) rd = _embedded_revise_draft(m) if rd: extras.append(rd[0]) trace_tags.append(rd[1]) rdiff = _embedded_revise_diff(m) if rdiff: extras.append(rdiff[0]) trace_tags.append(rdiff[1]) tg = _embedded_topic_guard(m) if tg: extras.append(tg[0]) trace_tags.append(tg[1]) tm = _embedded_topic_must(m) if tm: extras.append(tm[0]) trace_tags.append(tm[1]) af = _embedded_answer_frame(m) if af: extras.append(af[0]) trace_tags.append(af[1]) swot = _embedded_swot_analysis(m) if swot: extras.append(swot[0]) trace_tags.append(swot[1]) pest = _embedded_pestle_analysis(m) if pest: extras.append(pest[0]) trace_tags.append(pest[1]) cba = _embedded_cost_benefit(m) if cba: extras.append(cba[0]) trace_tags.append(cba[1]) oq = _embedded_open_questions(m) if oq: extras.append(oq[0]) trace_tags.append(oq[1]) scn = _embedded_scenario_cases(m) if scn: extras.append(scn[0]) trace_tags.append(scn[1]) pm = _embedded_postmortem_format(m) if pm: extras.append(pm[0]) trace_tags.append(pm[1]) srt = _embedded_sprint_retro(m) if srt: extras.append(srt[0]) trace_tags.append(srt[1]) ust = _embedded_user_story(m) if ust: extras.append(ust[0]) trace_tags.append(ust[1]) dod = _embedded_definition_of_done(m) if dod: extras.append(dod[0]) trace_tags.append(dod[1]) fw = _embedded_five_whys(m) if fw: extras.append(fw[0]) trace_tags.append(fw[1]) fb = _embedded_fishbone(m) if fb: extras.append(fb[0]) trace_tags.append(fb[1]) gls = _embedded_glossary_section(m) if gls: extras.append(gls[0]) trace_tags.append(gls[1]) spl = _embedded_spelling_locale(m) if spl: extras.append(spl[0]) trace_tags.append(spl[1]) tlo = _embedded_timeline_order(m) if tlo: extras.append(tlo[0]) trace_tags.append(tlo[1]) wvc = _embedded_writing_voice(m) if wvc: extras.append(wvc[0]) trace_tags.append(wvc[1]) fqa = _embedded_faq_qa_format(m) if fqa: extras.append(fqa[0]) trace_tags.append(fqa[1]) sml = _embedded_summary_last(m) if sml: extras.append(sml[0]) trace_tags.append(sml[1]) if _embedded_simple_audience(m): overrides["audience"] = "simple" elif _embedded_technical_audience(m): overrides["audience"] = "technical" ert = _embedded_register_tone(m) if ert: overrides["register_tone"] = ert oft = _embedded_output_format(m) if oft: overrides["output_format"] = oft vrb = _embedded_verbosity(m) if vrb: overrides["verbosity"] = vrb spc = _embedded_speculation(m) if spc: overrides["speculation"] = spc ald = _embedded_answer_lead(m) if ald: overrides["answer_lead"] = ald rcf = _embedded_recommendation_first(m) if rcf: extras.append(rcf[0]) trace_tags.append(rcf[1]) gng = _embedded_go_no_go(m) if gng: extras.append(gng[0]) trace_tags.append(gng[1]) act = _embedded_actionability(m) if act: overrides["actionability"] = act cft = _embedded_confidence_tone(m) if cft: overrides["confidence_tone"] = cft exd = _embedded_example_density(m) if exd: overrides["example_density"] = exd if len(m) < 48: return overrides, extras, trace_tags cmf = _embedded_comparison_frame(m) if cmf: overrides["comparison_frame"] = cmf stl = _embedded_step_style(m) if stl: overrides["step_style"] = stl tbl = _embedded_table_style(m) if tbl: overrides["table_style"] = tbl rpf = _embedded_reply_format(m) if rpf: overrides["reply_format"] = rpf mth = _embedded_math_detail(m) if mth: overrides["math_detail"] = mth cpt = _embedded_counterpoint_tone(m) if cpt: overrides["counterpoint_tone"] = cpt eord = _embedded_exposition_order(m) if eord: overrides["exposition_order"] = eord fuc = _embedded_followup_close(m) if fuc: overrides["followup_close"] = fuc clf = _embedded_clarify_first(m) if clf: overrides["clarify_first"] = clf shd = _embedded_section_headings(m) if shd: overrides["section_headings"] = shd anu = _embedded_analogy_use(m) if anu: overrides["analogy_use"] = anu tem = _embedded_term_emphasis(m) if tem: overrides["term_emphasis"] = tem acs = _embedded_acronym_style(m) if acs: overrides["acronym_style"] = acs rsk = _embedded_risk_posture(m) if rsk: overrides["risk_posture"] = rsk qst = _embedded_quote_style(m) if qst: overrides["quote_style"] = qst emj = _embedded_emoji_style(m) if emj: overrides["emoji_style"] = emj fgr = _embedded_faq_grounding(m) if fgr: overrides["faq_grounding"] = fgr cbs = _embedded_code_block_style(m) if cbs: overrides["code_block_style"] = cbs return overrides, extras, trace_tags