Governed Generation Tool UI Design¶
Date: 2026-04-05
Status: Draft
Supersedes: 2026-03-16-governed-chat-command-language-design.md (chat-based UI)
Summary¶
Governed Generation becomes a standard tool in the PhonoLex web app — same sidebar entry, same layout conventions, same UI patterns as Custom Word Lists, Contrastive Sets, and the other tools. No chat interface, no slash commands, no separate dashboard app. Clinicians compose constraints visually, write a prompt, hit Generate, and get output cards in a vertical feed with toggleable compliance analysis.
Core motivation: Position governed generation as a tool, not a chatbot. Clinicians configure and generate, same as they query word lists or build contrastive sets. The prompt is just another input field, not a conversation opener.
Position in the App¶
- Replaces
GovernedGenerationPlaceholderin the existing tool definitions - Lives in
packages/web/frontend/alongside all other tools - Sidebar: "Explore" section, purple accent (
#7E57C2), tool-oriented icon (not chat bubble) - Same
Boxwrapper,maxWidth: 1200, title + description header as other tools
Layout (Top to Bottom)¶
┌─────────────────────────────────────────────────────────┐
│ Tool Header: "Governed Generation" │
│ Description text + server status indicator │
├─────────────────────────────────────────────────────────┤
│ Constraint Accordions (configuration area) │
│ ▸ Phoneme Exclusion │
│ ▸ Phoneme Inclusion │
│ ▸ Psycholinguistic Bounds │
│ ▸ Structural │
│ ▸ Boosts │
│ ▸ Thematic │
├─────────────────────────────────────────────────────────┤
│ Active Constraints — dismissible chip summary row │
│ [/ɹ/ ×] [AoA ≤ 5 ×] [Include /k/ ~20% ×] │
├─────────────────────────────────────────────────────────┤
│ Prompt TextField (multiline) + Generate Button │
├─────────────────────────────────────────────────────────┤
│ Selection Toolbar (when cards selected) │
├─────────────────────────────────────────────────────────┤
│ Output Card (newest) │
│ Output Card │
│ Output Card (oldest) │
└─────────────────────────────────────────────────────────┘
Constraint Composition UI¶
Constraint configuration uses the same Accordion pattern as Builder's property filters — nested accordions by category, MUI inputs throughout.
Phoneme Exclusion¶
TextFieldwithIconButtonendAdornment openingPhonemePickerDialog- Same pattern as Builder's exclusion section
- Selected phonemes render as dismissible chips below the input
Phoneme Inclusion¶
- Same TextField + PhonemePickerDialog input pattern
- Each added phoneme gets a chip with an optional coverage target (
TextFieldorSliderfor percentage) - Strength control:
Slider
Psycholinguistic Bounds¶
- Mirrors Builder's property filter categories exactly
PropertySlider(two-thumb range slider) for each norm: AoA, concreteness, valence, arousal, imageability, familiarity, frequency, etc.- Same log-scale handling for frequency
- Same category grouping (Acquisition, Semantic, Sensorimotor, etc.)
Structural¶
- WCM max:
SliderorTextField(number) - Max syllables:
SliderorTextField - Allowed shapes:
ToggleButtonGroup(CV, CVC, CVCC, etc.) - MSH stage:
Selectdropdown (1–5)
Boosts¶
- Minimal pair boost: two phoneme inputs (target + contrast) + strength slider
- Maximal opposition boost: same pattern
- Vocab boost:
TextFieldfor word list, orSelectto pick from existing vocab lists
Thematic¶
- Seed words input:
TextField(space or comma separated) - Strength:
Slider
Active Constraint Summary¶
A row of dismissible chips between the configuration area and the prompt input — quick visual of what's active. Color coding:
| Color | Constraint Types |
|---|---|
| Red | Exclusion, cluster exclusion |
| Blue | Psycholinguistic bounds (AoA, concreteness...) |
| Green | Inclusion, vocab boost, minimal/maximal pair |
| Gray | Structural (complexity, MSH) |
| Purple | Thematic |
Prompt Input & Generation¶
- Multiline
TextFieldwith descriptive placeholder text - "Generate"
Button— full-width on mobile, right-aligned on desktop - Loading state:
CircularProgressinline on the button, button disabled during generation - No typing indicators, no "thinking" animation — standard form submission pattern
- Each generation is stateless: prompt + constraints in, output out
Output Cards¶
Cards stack in a vertical feed, newest on top. Each card has two states.
Default State (Clean Output)¶
Paper variant="outlined"(consistent with other tool results)- Generated text rendered as plain, readable, immediately usable text
- Slim footer row with at-a-glance metadata:
- Compliance badge: checkmark or violation count
- Token count
- Generation time
- Action buttons: Copy to clipboard, Regenerate (same prompt + constraints), Delete card
Analysis State (Toggle On)¶
- Toggle switch in the card header (or compliance badge acts as toggle)
- Text re-renders with token-level compliance overlay: red tint on violations, clickable tokens
- Clicking a token opens a popover with:
- Phonology: IPA, syllables, WCM, phonemes
- Norms: AoA, concreteness, valence, arousal, imageability, familiarity, frequency
- Compliance: which constraints were violated
- Constraint snapshot visible (chip row or expandable section) showing what was active when the card was generated
Selection & Export¶
- Checkbox on each card (same pattern as
WordListTableselection) SelectionToolbarappears when any cards are selected (count + actions)- Export options via
ExportMenudropdown: - Text file (.txt): Clean generated text only, one generation per block, blank line separated. Ready for therapy materials.
- CSV: One row per generation — columns for prompt, generated text, constraints used, compliance status, violation count, timestamp. For record-keeping or research.
- Both export only selected cards
API Integration¶
The tool component in the main web app calls the generation backend directly.
- Generation endpoint:
POST /api/generate-single— takes{ prompt, constraints }, returns{ tokens, text, gen_time_ms, compliant, violation_count } - Server status:
GET /api/server/status— used for status indicator near Generate button and cold start UX - API base URL: Configurable; points to wherever the generation backend is hosted (local, cloud, etc.)
- No backend changes needed — the existing
/api/generate-singleendpoint and response schema are exactly what this UI requires
Cold Start UX¶
The generation backend runs on serverless GPU infrastructure (e.g., RunPod Serverless) that scales to zero. When a worker is cold, model loading takes ~30-60 seconds. The UI handles this transparently:
- Pre-warm on tool open: When the clinician navigates to Governed Generation, fire a lightweight request to wake the worker immediately — before they've even composed constraints.
- Loading state: If the server status is "loading", show a prominent inline message: "Starting model server, please stand by (~1 min)" with a progress indicator. Generate button disabled during this state.
- Ready state: Once
/api/server/statusreturns "ready", the loading message disappears, Generate button enables, and a green "Server ready" chip confirms. - Idle timeout: Backend configured with 5-10 minute idle timeout so a clinician's session stays warm between generations.
What Moves from Dashboard to Web Frontend¶
Moves¶
ConstraintStore(Zustand) — same store shape, used by the new tool component- Constraint compilation logic (
compiler.ts) — compiles store entries to API format RichTokenSpan+TokenPopover— token-level compliance rendering- Chip color coding + label helpers
RichTokentype definitions and related schemas
New¶
GovernedGenerationToolcomponent (replaces placeholder)- Constraint accordion sections using existing MUI components (PhonemePickerDialog, PropertySlider, Select, etc.)
- Output card component with clean/analysis toggle
- Selection + export on cards
Dies¶
- Chat mode:
ChatWindow/,MessageList,MessageBubble,SystemMessage - Slash command system: parser, autocomplete, command registry,
CommandAutocomplete,IPAKeyboard(in chat context) ModeToggle(chat/generate toggle)GenerateWindow(replaced by card-based output)- Standalone dashboard app layout (
packages/dashboard/frontend/src/App.tsx) - Chat endpoint (
POST /api/generate) — deprecated; session tracking no longer needed
Card History¶
Card history is ephemeral — lives in component state, lost on page navigation. No persistence for v1.
Out of Scope¶
- Hosting/deployment of the generation backend — separate research track
- Preset profiles — constraints composed fresh each time; profiles can be added later
- Session/history persistence — ephemeral card history for now
- Streaming generation — full response returned at once
- Content Catalog integration — separate future feature
- Mobile optimization — desktop-first; responsive enough not to break, not a primary target