---
phase: 17-initiative-dashboard
plan: 03
type: execute
wave: 2
depends_on: ["17-01"]
files_modified:
  - packages/web/src/components/CreateInitiativeDialog.tsx
  - packages/web/src/components/SpawnArchitectDropdown.tsx
  - packages/web/src/components/ActionMenu.tsx
autonomous: true
---

<objective>
Build the interactive dialog and dropdown components: CreateInitiativeDialog, SpawnArchitectDropdown, and ActionMenu.

Purpose: These handle user actions — creating initiatives, spawning architect agents, and managing initiatives (edit/delete). They're independent of the card/list components and can be built in parallel.
Output: Three interactive components ready for page integration.
</objective>

<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md

@docs/wireframes/initiative-dashboard.md
@packages/web/src/components/ui/button.tsx
@packages/web/src/components/ui/dropdown-menu.tsx
@packages/web/src/lib/trpc.ts
@packages/shared/src/types.ts
@src/trpc/router.ts
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create CreateInitiativeDialog component</name>
  <files>packages/web/src/components/CreateInitiativeDialog.tsx</files>
  <action>
Create a dialog component for creating new initiatives.

**First, add shadcn/ui components needed:**
Run `npx shadcn@latest add dialog input label` from `packages/web/` to install the Dialog, Input, and Label components.

If the shadcn CLI creates files in a literal `@/` directory (known issue from 16-04), move them to `packages/web/src/components/ui/` manually.

**Component structure:**
- Controlled dialog with `open` and `onOpenChange` props
- Form fields: Name (required text input), Description (optional textarea)
- Buttons: Cancel (closes dialog), Create (submits form)

**Mutation:**
- Use `trpc.createInitiative.useMutation()` to create the initiative
- On success: close dialog, invalidate `listInitiatives` query via `utils.listInitiatives.invalidate()`
- On error: show error text below form
- While submitting: disable Create button, show "Creating..." text

**Form handling:**
- Use React `useState` for form fields (name, description)
- Validate name is non-empty before enabling Create button
- Reset form fields when dialog opens (use `useEffect` on `open` prop)

No external form libraries — useState is sufficient for 2 fields.

Export: `export function CreateInitiativeDialog`.
  </action>
  <verify>npx tsc --noEmit -p packages/web/tsconfig.app.json</verify>
  <done>CreateInitiativeDialog opens modal, accepts name/description, creates initiative via tRPC, handles loading/error states</done>
</task>

<task type="auto">
  <name>Task 2: Create SpawnArchitectDropdown and ActionMenu components</name>
  <files>packages/web/src/components/SpawnArchitectDropdown.tsx, packages/web/src/components/ActionMenu.tsx</files>
  <action>
**SpawnArchitectDropdown:**

Create a dropdown for spawning architect agents in different modes.

Props:
- `initiativeId: string`
- `initiativeName: string` — used to generate agent name

Uses the existing DropdownMenu from shadcn/ui. Two menu items:
- "Discuss" — calls `trpc.spawnArchitectDiscuss.useMutation()` with `{ name: initiativeName + '-discuss', initiativeId }`
- "Breakdown" — calls `trpc.spawnArchitectBreakdown.useMutation()` with `{ name: initiativeName + '-breakdown', initiativeId }`

On success: close dropdown. Optionally show a brief success state (text change on button).
On error: keep dropdown open, show error. Use a simple approach — just console.error for now, toast notifications come in Phase 21.

The trigger button text: "Spawn Architect" with a chevron-down icon from lucide-react.

**ActionMenu:**

Create a "more actions" dropdown for initiative management.

Props:
- `initiativeId: string`
- `onDelete: () => void` — callback after deletion

Menu items per wireframe:
- "Edit" — disabled for now (placeholder, no edit form in Phase 17 scope)
- "Duplicate" — disabled for now (placeholder)
- "Archive" — calls `trpc.updateInitiative.useMutation()` with `{ id: initiativeId, status: 'archived' }`, then invalidates queries
- "Delete" — calls `trpc.updateInitiative.useMutation()` or a delete procedure if available. Since there's no `deleteInitiative` tRPC procedure visible, use archive as the destructive action. Add a browser `confirm()` dialog before archive/delete.

Actually, check if `deleteInitiative` exists on the router. The InitiativeRepository interface has `delete(id)` but the tRPC router may not expose it. If not exposed, skip Delete and only implement Archive as the destructive action. Mark Delete as disabled/placeholder.

The trigger button: an ellipsis icon (MoreHorizontal from lucide-react) with ghost variant.

Export both as named exports.
  </action>
  <verify>npx tsc --noEmit -p packages/web/tsconfig.app.json</verify>
  <done>SpawnArchitectDropdown triggers discuss/breakdown mutations, ActionMenu provides archive action with confirmation</done>
</task>

</tasks>

<verification>
Before declaring plan complete:
- [ ] `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes
- [ ] Dialog, Input, Label shadcn components installed
- [ ] CreateInitiativeDialog creates initiatives via tRPC mutation
- [ ] SpawnArchitectDropdown calls correct architect spawn procedures
- [ ] ActionMenu shows archive action with confirmation
</verification>

<success_criteria>

- CreateInitiativeDialog creates initiatives with name and description
- SpawnArchitectDropdown triggers discuss and breakdown modes
- ActionMenu provides archive (and disabled placeholders for edit/duplicate/delete)
- All mutations invalidate relevant queries on success
- TypeScript compiles without errors
  </success_criteria>

<output>
After completion, create `.planning/phases/17-initiative-dashboard/17-03-SUMMARY.md`
</output>
