mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
* [50e80c55] docs(design): create Prompter interaction design directory and main spec * [50e80c55] docs(design): add confirmation interstitial spec with un-bypassable guardrails * [50e80c55] docs(design): add model-selector drawer UX with Recommended default and complexity mapping * [50e80c55] docs(design): add naming and navigation spec with sidebar placement and Task Assistant recommendation --------- Co-authored-by: UX/UI Developer 1 <ux-dev-1@agents.roboco.dev>
207 lines
11 KiB
Markdown
207 lines
11 KiB
Markdown
# Prompter — Confirmation Interstitial Specification
|
||
|
||
## Principle
|
||
|
||
> **You decide what gets sent to the team.**
|
||
|
||
The confirmation interstitial is the un-bypassable human gate before any Prompter-generated task enters the RoboCo system. It must be impossible to skip by accident, by keyboard shortcut, or by API manipulation. The user must read, review, and explicitly confirm.
|
||
|
||
---
|
||
|
||
## Pattern: Review & Confirm Dialog
|
||
|
||
### Component
|
||
|
||
`Dialog` from `panel/src/components/ui/dialog.tsx` — **not** `AlertDialog`. We need the full content flexibility of `Dialog` (close button, scrollable body, custom footer) rather than the simplified action/cancel binary of `AlertDialog`.
|
||
|
||
**Size**: `DialogContent` with classes `sm:max-w-3xl lg:max-w-4xl max-h-[90vh] overflow-y-auto`.
|
||
|
||
This is the same large-dialog pattern used by `CreateTaskDialog` in `panel/src/components/tasks/create-task-dialog.tsx`.
|
||
|
||
---
|
||
|
||
## Layout
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ Review & Confirm Task [×] │
|
||
│ You decide what gets sent to the team. │
|
||
├──────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Title * │
|
||
│ [________________________________________] │
|
||
│ │
|
||
│ Description * │
|
||
│ [ ] │
|
||
│ [ Markdown editor with preview toggle ] │
|
||
│ [ ] │
|
||
│ │
|
||
│ Acceptance Criteria * │
|
||
│ ┌────────────────────────────────────────┐ │
|
||
│ │ 1. [Criterion text………] [×] │ │
|
||
│ │ 2. [Criterion text………] [×] │ │
|
||
│ │ 3. [Criterion text………] [×] │ │
|
||
│ │ [+ Add Criterion] │ │
|
||
│ └────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌──────────┬──────────┬──────────┬──────────┐ │
|
||
│ │ Team │ Status │ Priority │ Complex. │ │
|
||
│ │ [Select] │ [Select] │ [Select] │ [Select] │ │
|
||
│ └──────────┴──────────┴──────────┴──────────┘ │
|
||
│ │
|
||
│ ┌─ Advanced Options ──────────────────────┐ │
|
||
│ │ Model selector (see model-selector-ux.md) │ │
|
||
│ │ Assign to, Parent task, Project, Product │ │
|
||
│ └──────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌────────────────────────────────────────────────────────┐ │
|
||
│ │ ⚠️ This will create a real task and notify the team. │ │
|
||
│ │ It cannot be undone from this screen. │ │
|
||
│ └────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
├──────────────────────────────────────────────────────────────┤
|
||
│ [Cancel] [Confirm & Launch]│
|
||
└──────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Sections (Detailed)
|
||
|
||
### 1. Dialog Header
|
||
|
||
- **Title**: `DialogTitle` — "Review & Confirm Task"
|
||
- **Description**: `DialogDescription` — "You decide what gets sent to the team."
|
||
|
||
Both are required and always visible. The description is the human-agency anchor copy mandated by the Head of Marketing.
|
||
|
||
### 2. Title Field
|
||
|
||
- `Label` + `Input`
|
||
- Required (`*` indicator, `text-destructive` color)
|
||
- Validation: 5–200 characters (same rule as `CreateTaskDialog`)
|
||
- Error state: `border-destructive` + `text-xs text-destructive` message
|
||
- Pre-filled by LLM draft; user can edit inline.
|
||
|
||
### 3. Description Field
|
||
|
||
- Reuse `MarkdownEditor` from `panel/src/components/tasks/markdown-editor.tsx`
|
||
- Required, min 20 characters
|
||
- Preview toggle (Edit / Preview tabs using `Tabs` component)
|
||
- Pre-filled by LLM draft; user can edit inline.
|
||
|
||
### 4. Acceptance Criteria
|
||
|
||
- Reuse `AcceptanceCriteriaEditor` from `panel/src/components/tasks/acceptance-criteria-editor.tsx`
|
||
- Required, at least one criterion
|
||
- Numbered list with drag handles (if the existing editor supports reordering) or simple add/remove
|
||
- Pre-filled by LLM draft; user can add, edit, remove.
|
||
|
||
### 5. Metadata Grid
|
||
|
||
A 4-column grid (`grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4`) using `Select` components:
|
||
|
||
| Field | Component | Options | Default (from draft) |
|
||
|-------|-----------|---------|----------------------|
|
||
| Team | `Select` | `Object.values(Team)` | LLM suggestion |
|
||
| Status | `Select` | `PENDING`, `BACKLOG` | `PENDING` |
|
||
| Priority | `Select` | `P0`–`P3` | `P2` (Medium) |
|
||
| Complexity | `Select` | `LOW`, `MEDIUM`, `HIGH` | LLM suggestion |
|
||
|
||
All wrapped in `Label` + `SelectTrigger` + `SelectContent` + `SelectItem`.
|
||
|
||
### 6. Advanced Options Drawer
|
||
|
||
- `Collapsible` from `panel/src/components/ui/collapsible.tsx`
|
||
- Trigger: `Button` variant `ghost` with `ChevronRight` / `ChevronDown` icons
|
||
- Contents:
|
||
- **Model selector** — see [`03-model-selector-ux.md`](03-model-selector-ux.md)
|
||
- **Assign To** — `AgentSelector` (`panel/src/components/agents/agent-selector.tsx`)
|
||
- **Parent Task** — `TaskSelector` (`panel/src/components/tasks/task-selector.tsx`)
|
||
- **Project** — `ProjectSelector` (`panel/src/components/projects/project-selector.tsx`)
|
||
- **Product** — `Select` from `CreateTaskDialog` product list
|
||
|
||
### 7. Warning Banner
|
||
|
||
A full-width `Alert` (if available; otherwise a `Card` with `border-destructive` or `bg-destructive/10`):
|
||
|
||
- Icon: `AlertTriangle` from `lucide-react`
|
||
- Text: "This will create a real task and notify the team. It cannot be undone from this screen."
|
||
- Purpose: prevents the "I thought this was just a preview" error.
|
||
|
||
### 8. Footer Actions
|
||
|
||
- `DialogFooter` with `flex-col-reverse sm:flex-row sm:justify-end gap-2`
|
||
- **Cancel** (`Button` variant `outline`): closes dialog, returns to chat draft preview. Does **not** discard the draft.
|
||
- **Confirm & Launch** (`Button` primary): submits to the task-creation API.
|
||
- On click: button enters `disabled` state, text changes to "Launching…", spinner (use `Loader2` icon with `animate-spin`)
|
||
- On success: dialog closes, chat shows success card
|
||
- On error: button re-enables, error banner appears above footer
|
||
|
||
---
|
||
|
||
## Un-bypassable Guardrails
|
||
|
||
### UI Guardrails
|
||
|
||
1. **No keyboard shortcut** launches the task. `Enter` inside any field does **not** submit the form; only the explicit footer button does.
|
||
2. **No click-outside dismissal** when dirty. If the user has edited any field, clicking the overlay shows a secondary confirmation: "You have unsaved changes. Discard them?" (`AlertDialog` with "Keep Editing" / "Discard").
|
||
3. **Scroll requirement**: The dialog is tall enough that the footer may be below the fold on small screens. The warning banner is positioned **above** the footer so the user must scroll past it to reach the confirm button.
|
||
|
||
### API Guardrails (Frontend Contract)
|
||
|
||
- The frontend must **not** call the task-creation endpoint directly from the chat state. The only valid call path is:
|
||
```
|
||
Chat → Review Modal (user opens) → Confirm Button (user clicks) → POST /tasks
|
||
```
|
||
- There is no `?skip_review=true` query param, no hidden route, and no keyboard bypass.
|
||
- Backend should reject any Prompter-originated task creation that does not include a `confirmed_by_human: true` flag in the payload (enforced by the Backend Cell; noted here for cross-cell alignment).
|
||
|
||
---
|
||
|
||
## Accessibility
|
||
|
||
- Focus trap: when dialog opens, focus moves to the Title `Input`.
|
||
- `aria-describedby` on the Confirm button pointing to the warning banner text.
|
||
- All `Select` triggers have visible `Label` associations (`htmlFor` + `id`).
|
||
- Error messages use `aria-live="assertive"` so screen readers announce validation failures immediately.
|
||
|
||
---
|
||
|
||
## Copy Reference
|
||
|
||
| Element | Copy |
|
||
|---------|------|
|
||
| Dialog title | "Review & Confirm Task" |
|
||
| Dialog subtitle | "You decide what gets sent to the team." |
|
||
| Warning banner | "This will create a real task and notify the team. It cannot be undone from this screen." |
|
||
| Cancel button | "Cancel" |
|
||
| Confirm button (idle) | "Confirm & Launch" |
|
||
| Confirm button (loading) | "Launching…" |
|
||
| Dirty-state discard prompt title | "Discard changes?" |
|
||
| Dirty-state discard prompt body | "You have unsaved changes. If you cancel, your edits will be lost." |
|
||
| Dirty-state keep button | "Keep Editing" |
|
||
| Dirty-state discard button | "Discard" |
|
||
|
||
---
|
||
|
||
## Component Inventory
|
||
|
||
| UI Element | File Path |
|
||
|------------|-----------|
|
||
| Dialog shell | `panel/src/components/ui/dialog.tsx` |
|
||
| Alert (warning banner) | `panel/src/components/ui/alert-dialog.tsx` or custom `Card` |
|
||
| Card | `panel/src/components/ui/card.tsx` |
|
||
| Input | `panel/src/components/ui/input.tsx` |
|
||
| Textarea / MarkdownEditor | `panel/src/components/tasks/markdown-editor.tsx` |
|
||
| Select | `panel/src/components/ui/select.tsx` |
|
||
| Label | `panel/src/components/ui/label.tsx` |
|
||
| Button | `panel/src/components/ui/button.tsx` |
|
||
| Collapsible | `panel/src/components/ui/collapsible.tsx` |
|
||
| Badge | `panel/src/components/ui/badge.tsx` |
|
||
| Tabs | `panel/src/components/ui/tabs.tsx` |
|
||
| AcceptanceCriteriaEditor | `panel/src/components/tasks/acceptance-criteria-editor.tsx` |
|
||
| AgentSelector | `panel/src/components/agents/agent-selector.tsx` |
|
||
| TaskSelector | `panel/src/components/tasks/task-selector.tsx` |
|
||
| ProjectSelector | `panel/src/components/projects/project-selector.tsx` |
|