Phase 19: Agent Inbox - 4 plans in 2 waves - 3 parallel (Wave 1), 1 sequential (Wave 2) - Ready for execution
5.2 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous
| phase | plan | type | wave | depends_on | files_modified | autonomous | |||
|---|---|---|---|---|---|---|---|---|---|
| 19-agent-inbox | 03 | execute | 1 |
|
true |
Purpose: Agents ask structured questions with options (radio/checkbox), multi-select, free-text, and "Other" fields. These components render the question forms inside the message detail view. Following the wireframe spec from docs/wireframes/agent-inbox.md.
Output: QuestionForm, OptionGroup, and FreeTextInput components.
<execution_context>
@/.claude/get-shit-done/workflows/execute-plan.md
@/.claude/get-shit-done/templates/summary.md
</execution_context>
@docs/wireframes/agent-inbox.md @src/agent/types.ts @packages/web/src/components/ui/input.tsx @packages/web/src/components/ui/label.tsx @packages/web/src/components/ui/textarea.tsx @packages/web/src/components/ui/button.tsx
Task 1: Create OptionGroup and FreeTextInput components packages/web/src/components/OptionGroup.tsx, packages/web/src/components/FreeTextInput.tsx **OptionGroup** — renders radio buttons OR checkboxes for a question's options. Props: - `questionId: string` — for form identification - `options: Array<{ label: string; description?: string }>` — available choices - `multiSelect: boolean` — checkboxes (true) or radio buttons (false) - `value: string` — current selection (for radio: single label, for checkbox: comma-separated labels) - `onChange: (value: string) => void` — change handler - `allowOther?: boolean` — show "Other" free-text option (default true)Behavior:
- Radio buttons for single-select (default). Use native HTML radio inputs with Tailwind styling.
- Checkboxes for multi-select. Use native HTML checkbox inputs with Tailwind styling.
- Each option shows label and optional description in lighter text
- "Other" option: text input that auto-selects its radio/checkbox when user types. The "Other" value is whatever the user typed.
- For multi-select, value is comma-joined selected labels. When "Other" is checked, append the typed text.
FreeTextInput — renders when question has NO options (pure free-text). Props:
questionId: stringvalue: stringonChange: (value: string) => voidmultiline?: boolean— textarea vs single input (default false)placeholder?: string
Use shadcn Input for single-line, shadcn Textarea for multiline. Keep it simple. npx tsc --noEmit -p packages/web/tsconfig.app.json - OptionGroup renders radio or checkbox based on multiSelect prop - "Other" field auto-selects when typed into - FreeTextInput renders Input or Textarea based on multiline prop
Task 2: Create QuestionForm component packages/web/src/components/QuestionForm.tsx QuestionForm orchestrates rendering multiple questions with mixed input types. Props: - `questions: Array<{ id: string; question: string; options?: Array<{ label: string; description?: string }>; multiSelect?: boolean }>` — structured question data from agent - `onSubmit: (answers: Record) => void` — submit handler with questionId→answer map - `onCancel: () => void` — cancel handler - `isSubmitting?: boolean` — disable form during submissionInternal state:
answers: Record<string, string>— maps question ID to answer string
Behavior:
- Render each question sequentially with "Q1:", "Q2:", etc. prefix and question text
- For each question, determine input type:
- If
optionsarray exists → render OptionGroup (with multiSelect from question) - If no options → render FreeTextInput
- If
- Track answers in local state via
onAnswerChangecallbacks - "Send Answers" button: enabled only when ALL questions have non-empty answers
- "Cancel" button: always enabled
- On submit: call
onSubmit(answers)with the complete answer map - Button row at bottom: [Cancel] [Send Answers] — right-aligned, matching wireframe
Use shadcn Button for actions. npx tsc --noEmit -p packages/web/tsconfig.app.json - QuestionForm renders mixed question types from questions array - Submit disabled until all questions answered - onSubmit called with Record<string, string> mapping questionId to answer
Before declaring plan complete: - [ ] `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes - [ ] `npx vite build` in packages/web succeeds<success_criteria>
- OptionGroup handles radio (single-select) and checkbox (multi-select) with "Other" field
- FreeTextInput handles single-line and multiline inputs
- QuestionForm renders sequential questions with correct input type per question
- Submit validates all questions answered
- All builds pass </success_criteria>